453 lines
21 KiB
C#
453 lines
21 KiB
C#
using Adaptation.Shared;
|
|
using Adaptation.Shared.Metrology;
|
|
using log4net;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Text.Json;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace Adaptation.Helpers
|
|
{
|
|
|
|
public partial class ProcessData : IProcessData
|
|
{
|
|
|
|
public HgProbeFile Header { get; private set; }
|
|
public List<HgProbeDetail> Details { get; private set; }
|
|
|
|
private int _I;
|
|
private readonly ILog _Log;
|
|
private string _Data;
|
|
|
|
public ProcessData(ILogic logic, ConfigData configData, List<FileInfo> fileInfoCollection)
|
|
{
|
|
Header = null;
|
|
fileInfoCollection.Clear();
|
|
_I = 0;
|
|
_Data = string.Empty;
|
|
_Log = LogManager.GetLogger(typeof(ProcessData));
|
|
Details = new List<HgProbeDetail>();
|
|
Tuple<HgProbeFile, List<HgProbeDetail>> tuple = Parse(logic, configData, fileInfoCollection);
|
|
Details.AddRange(tuple.Item2);
|
|
Header = tuple.Item1;
|
|
}
|
|
|
|
public Tuple<string, JsonElement?, List<FileInfo>> GetResults(ILogic logic, ConfigDataBase configDataBase, List<FileInfo> fileInfoCollection)
|
|
{
|
|
Tuple<string, JsonElement?, List<FileInfo>> results;
|
|
if (!(configDataBase is ConfigData configData))
|
|
throw new Exception();
|
|
List<Test> tests = new List<Test>();
|
|
List<IProcessDataDescription> descriptions;
|
|
EventName eventName = configData.GetEventNameValue();
|
|
if (eventName == EventName.FileRead && Details.Any())
|
|
{
|
|
foreach (var item in Details)
|
|
tests.Add(Test.HgCV);
|
|
descriptions = configData.GetDescription(logic, tests, this);
|
|
}
|
|
else
|
|
throw new Exception();
|
|
if (!configData.EafHosted)
|
|
{
|
|
new FileRead.Description().GetDescription(logic, configData, tests, this);
|
|
}
|
|
if (tests.Count != descriptions.Count)
|
|
throw new Exception();
|
|
for (int i = 0; i < tests.Count; i++)
|
|
{
|
|
if (descriptions[i].Test != (int)tests[i])
|
|
throw new Exception();
|
|
}
|
|
string json;
|
|
if (descriptions[0] is Duplicator.Description)
|
|
{
|
|
List<Duplicator.Description> duplicatorDescriptions = (from l in descriptions select (Duplicator.Description)l).ToList();
|
|
json = JsonSerializer.Serialize(duplicatorDescriptions, duplicatorDescriptions.GetType());
|
|
}
|
|
else if (descriptions[0] is FileRead.Description)
|
|
{
|
|
List<FileRead.Description> fileReadDescriptions = (from l in descriptions select (FileRead.Description)l).ToList();
|
|
json = JsonSerializer.Serialize(fileReadDescriptions, fileReadDescriptions.GetType());
|
|
}
|
|
else
|
|
throw new Exception();
|
|
object @object = JsonSerializer.Deserialize<object>(json);
|
|
if (!(@object is JsonElement jsonElement))
|
|
throw new Exception();
|
|
results = new Tuple<string, JsonElement?, List<FileInfo>>(logic.Logistics.Logistics1[0], jsonElement, fileInfoCollection);
|
|
return results;
|
|
}
|
|
|
|
public static Dictionary<Test, List<Duplicator.Description>> GetKeyValuePairs(ConfigData configData, JsonElement jsonElement, List<Duplicator.Description> processDataDescriptions, bool extra = false)
|
|
{
|
|
Dictionary<Test, List<Duplicator.Description>> results = configData.GetKeyValuePairs(processDataDescriptions);
|
|
configData.CheckProcessDataDescription(results, extra);
|
|
return results;
|
|
}
|
|
|
|
public static List<FileRead.Description> GetProcessDataFileReadDescriptions(ConfigData configData, JsonElement jsonElement)
|
|
{
|
|
List<FileRead.Description> results = new List<FileRead.Description>();
|
|
List<IProcessDataDescription> processDataDescriptions = configData.GetIProcessDataDescriptions(jsonElement);
|
|
foreach (IProcessDataDescription processDataDescription in processDataDescriptions)
|
|
{
|
|
if (!(processDataDescription is FileRead.Description description))
|
|
continue;
|
|
results.Add(description);
|
|
}
|
|
return results;
|
|
}
|
|
|
|
public static string GetLines(ILogic logic, List<FileRead.Description> descriptions)
|
|
{
|
|
StringBuilder result = new StringBuilder();
|
|
return result.ToString();
|
|
}
|
|
|
|
internal static void PostOpenInsightMetrologyViewerAttachments(ILog log, ConfigData configData, Logistics logistics, DateTime dateTime, string logisticsSequenceMemoryDirectory, List<FileRead.Description> descriptions, string matchDirectory)
|
|
{
|
|
string[] pclFiles = Directory.GetFiles(matchDirectory, "*.pcl", SearchOption.TopDirectoryOnly);
|
|
if (pclFiles.Length != 1)
|
|
throw new Exception("Invalid source file count!");
|
|
string wsResultsMemoryFile = string.Concat(logisticsSequenceMemoryDirectory, @"\", nameof(WS.Results), ".json");
|
|
if (!File.Exists(wsResultsMemoryFile))
|
|
throw new Exception(string.Concat("Memory file <", wsResultsMemoryFile, "> doesn't exist!"));
|
|
string json = File.ReadAllText(wsResultsMemoryFile);
|
|
WS.Results metrologyWSRequest = JsonSerializer.Deserialize<WS.Results>(json);
|
|
long wsResultsHeaderID = metrologyWSRequest.HeaderID;
|
|
List<string> pdfFiles = new List<string>();
|
|
pdfFiles.AddRange(Directory.GetFiles(matchDirectory, "*.pdf_old", SearchOption.TopDirectoryOnly));
|
|
foreach (string pdfFile in pdfFiles)
|
|
File.Delete(pdfFile);
|
|
pdfFiles.Clear();
|
|
pdfFiles.AddRange(Directory.GetFiles(matchDirectory, "*.pdf", SearchOption.TopDirectoryOnly));
|
|
foreach (string pdfFile in pdfFiles)
|
|
File.Move(pdfFile, Path.ChangeExtension(pdfFile, ".pdf_old"));
|
|
pdfFiles.Clear();
|
|
foreach (string pclFile in pclFiles.OrderBy(l => l))
|
|
pdfFiles.Add(ConvertSourceFileToPdfWithChartData(configData, pclFile));
|
|
if (pdfFiles.Count == 0)
|
|
log.Debug("Invalid *.pdf file count!");
|
|
List<WS.Attachment> headerAttachments = new List<WS.Attachment> { new WS.Attachment(descriptions[0].HeaderUniqueId, "Data.pdf", pdfFiles[0]) };
|
|
WS.AttachFiles(configData.OpenInsightMetrogyViewerAPI, wsResultsHeaderID, headerAttachments, dataAttachments: null);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert the raw data file to parsable file format - in this case from PCL to PDF
|
|
/// </summary>
|
|
/// <param name="sourceFile">source file to be converted to PDF</param>
|
|
/// <returns></returns>
|
|
private static string ConvertSourceFileToPdf(ConfigData configData, string sourceFile)
|
|
{
|
|
string result = Path.ChangeExtension(sourceFile, ".pdf");
|
|
if (!File.Exists(result))
|
|
{
|
|
//string arguments = string.Concat("-i \"", sourceFile, "\" -o \"", result, "\"");
|
|
string arguments = string.Concat("-dSAFER -dBATCH -dNOPAUSE -dFIXEDMEDIA -dFitPage -dAutoRotatePages=/All -dDEVICEWIDTHPOINTS=792 -dDEVICEHEIGHTPOINTS=612 -sOutputFile=\"", result, "\" -sDEVICE=pdfwrite \"", sourceFile, "\"");
|
|
//Process process = Process.Start(configData.LincPDFCFileName, arguments);
|
|
Process process = Process.Start(configData.GhostPCLFileName, arguments);
|
|
process.WaitForExit(30000);
|
|
if (!File.Exists(result))
|
|
throw new Exception("PDF file wasn't created");
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert the raw data file to parsable file format - in this case from PCL to PDF
|
|
/// </summary>
|
|
/// <param name="sourceFile">source file to be converted to PDF</param>
|
|
/// <returns></returns>
|
|
private static string ConvertSourceFileToPdfWithChartData(ConfigData configData, string sourceFile)
|
|
{
|
|
string result = Path.ChangeExtension(sourceFile, ".pdf");
|
|
if (!File.Exists(result))
|
|
{
|
|
string arguments = string.Concat("-i \"", sourceFile, "\" -o \"", result, "\"");
|
|
//string arguments = string.Concat("-dSAFER -dBATCH -dNOPAUSE -dFIXEDMEDIA -dFitPage -dAutoRotatePages=/All -dDEVICEWIDTHPOINTS=792 -dDEVICEHEIGHTPOINTS=612 -sOutputFile=\"", result, "\" -sDEVICE=pdfwrite \"", sourceFile, "\"");
|
|
Process process = Process.Start(configData.LincPDFCFileName, arguments);
|
|
//Process process = Process.Start(configData.GhostPCLFileName, arguments);
|
|
process.WaitForExit(30000);
|
|
if (!File.Exists(result))
|
|
throw new Exception("PDF file wasn't created");
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private void ScanPast(string text)
|
|
{
|
|
int num = _Data.IndexOf(text, _I);
|
|
if (num > -1)
|
|
{
|
|
_I = num + text.Length;
|
|
}
|
|
else
|
|
{
|
|
_I = _Data.Length;
|
|
}
|
|
}
|
|
|
|
private string GetBefore(string text)
|
|
{
|
|
int num = _Data.IndexOf(text, _I);
|
|
string text2;
|
|
if (num > -1)
|
|
{
|
|
text2 = _Data.Substring(_I, num - _I);
|
|
_I = num + text.Length;
|
|
return text2.Trim();
|
|
}
|
|
text2 = _Data.Substring(_I);
|
|
_I = _Data.Length;
|
|
return text2.Trim();
|
|
}
|
|
|
|
private bool IsNullOrWhiteSpace(string text)
|
|
{
|
|
for (int i = 0; i < text.Length; i++)
|
|
{
|
|
if (!char.IsWhiteSpace(text[i]))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private bool IsBlankLine()
|
|
{
|
|
int num = _Data.IndexOf("\n", _I);
|
|
return IsNullOrWhiteSpace((num > -1) ? _Data.Substring(_I, num - _I) : _Data.Substring(_I));
|
|
}
|
|
|
|
private string GetToEOL()
|
|
{
|
|
return GetBefore("\n");
|
|
}
|
|
|
|
private string GetToken()
|
|
{
|
|
while (_I < _Data.Length && IsNullOrWhiteSpace(_Data.Substring(_I, 1)))
|
|
{
|
|
_I++;
|
|
}
|
|
int j;
|
|
for (j = _I; j < _Data.Length && !IsNullOrWhiteSpace(_Data.Substring(j, 1)); j++)
|
|
{
|
|
}
|
|
string text = _Data.Substring(_I, j - _I);
|
|
_I = j;
|
|
return text.Trim();
|
|
}
|
|
|
|
private Tuple<HgProbeFile, List<HgProbeDetail>> Parse(ILogic logic, ConfigData configData, List<FileInfo> fileInfoCollection)
|
|
{
|
|
Tuple<HgProbeFile, List<HgProbeDetail>> result;
|
|
string headerText;
|
|
string sourceFileNamePdf = ConvertSourceFileToPdf(configData, logic.Logistics.ReportFullPath);
|
|
fileInfoCollection.Add(new FileInfo(sourceFileNamePdf));
|
|
string altHeaderFileName = Path.ChangeExtension(logic.Logistics.ReportFullPath, ".txt");
|
|
if (File.Exists(altHeaderFileName))
|
|
{
|
|
headerText = File.ReadAllText(altHeaderFileName);
|
|
fileInfoCollection.Add(new FileInfo(altHeaderFileName));
|
|
}
|
|
else
|
|
{
|
|
//Pdfbox, IKVM.AWT.WinForms
|
|
org.apache.pdfbox.pdmodel.PDDocument pdfDocument = org.apache.pdfbox.pdmodel.PDDocument.load(sourceFileNamePdf);
|
|
org.apache.pdfbox.util.PDFTextStripper stripper = new org.apache.pdfbox.util.PDFTextStripper();
|
|
headerText = stripper.getText(pdfDocument);
|
|
pdfDocument.close();
|
|
File.AppendAllText(altHeaderFileName, headerText);
|
|
fileInfoCollection.Add(new FileInfo(altHeaderFileName));
|
|
}
|
|
List<HgProbeDetail> hgProbeDetails = new List<HgProbeDetail>();
|
|
HgProbeFile hgProbeFile = new HgProbeFile { JobID = logic.Logistics.JobID, MesEntity = logic.Logistics.MesEntity, Date = DateTime.Now.ToString() };
|
|
string h = string.Empty;
|
|
if (headerText.Contains("G A T E V O L T A G E"))
|
|
throw new Exception("Ignore: GATEVOLTAGE runs are not parsed.");
|
|
if (!string.IsNullOrEmpty(headerText))
|
|
{
|
|
headerText = headerText.Replace("box", "");
|
|
headerText = headerText.Replace("bar", "");
|
|
headerText = headerText.Replace("horiz", "");
|
|
headerText = headerText.Replace("center", "");
|
|
headerText = headerText.Replace("upper", "");
|
|
headerText = headerText.Replace("lower", "");
|
|
headerText = headerText.Replace("right", "");
|
|
headerText = headerText.Replace("left", "");
|
|
headerText = headerText.Replace("thin", "");
|
|
headerText = headerText.Replace("vertical", "");
|
|
headerText = headerText.Replace("line", "");
|
|
headerText = headerText.Replace("middle", "");
|
|
headerText = headerText.Replace("side", "");
|
|
headerText = headerText.Replace("top", ""); // This will change "Stop Voltage" to "S Voltage"
|
|
headerText = headerText.Replace("corner", "");
|
|
headerText = headerText.Replace("bottom", "");
|
|
headerText = headerText.Replace("ruleunder", "_");
|
|
headerText = headerText.Replace("@", "");
|
|
headerText = headerText.Replace("*", "");
|
|
_I = 0;
|
|
_Data = headerText;
|
|
_Log.Debug($"****MERCURY-DATA [002]= {headerText}");
|
|
ScanPast("Operator:");
|
|
hgProbeFile.Employee = GetBefore("Start Voltage:");
|
|
hgProbeFile.StartVoltage = GetBefore("V");
|
|
ScanPast("Wafer :");
|
|
hgProbeFile.Wafer = GetBefore("S Voltage :"); // This is actually "Stop Voltage"
|
|
hgProbeFile.StopVoltage = GetBefore("V");
|
|
ScanPast("Lot :");
|
|
if (headerText.Contains("Ramp Rate :"))
|
|
hgProbeFile.Lot = GetBefore("Ramp Rate :");
|
|
else if (headerText.Contains("Forward Rate :"))
|
|
hgProbeFile.Lot = GetBefore("Forward Rate :");
|
|
else if (headerText.Contains("Conduct Type:"))
|
|
hgProbeFile.Lot = GetBefore("Conduct Type:");
|
|
else
|
|
hgProbeFile.Lot = string.Empty;
|
|
// Remove illegal characters \/:*?"<>| found in the Lot.
|
|
hgProbeFile.Lot = Regex.Replace(hgProbeFile.Lot, @"[\\,\/,\:,\*,\?,\"",\<,\>,\|]", "_").Split('\r')[0].Split('\n')[0];
|
|
hgProbeFile.RampRate = GetBefore("mV/sec");
|
|
ScanPast("Plan :");
|
|
hgProbeFile.Plan = GetBefore("G limit :");
|
|
//hgProbeFile.GLimit = GetBefore("S ");
|
|
hgProbeFile.GLimit = GetBefore("S");
|
|
hgProbeFile.Date = DateTime.Now.ToString();
|
|
ScanPast("Setup File:");
|
|
//hgProbeFile.SetupFile = GetBefore("O O");
|
|
hgProbeFile.SetupFile = GetBefore("O O");
|
|
ScanPast("Wafer size :");
|
|
hgProbeFile.WaferSize = GetBefore("mm");
|
|
ScanPast("Folder :");
|
|
//hgProbeFile.Folder = GetBefore("N N");
|
|
hgProbeFile.Folder = GetBefore("N N");
|
|
ScanPast("Ccomp : ");
|
|
hgProbeFile.Ccomp = GetBefore("pF");
|
|
ScanPast("Pattern :");
|
|
//hgProbeFile.Pattern = GetBefore("C C");
|
|
hgProbeFile.Pattern = GetBefore("C C");
|
|
ScanPast("Area:");
|
|
hgProbeFile.Area = GetBefore("cm2");
|
|
ScanPast("Cond Type :");
|
|
hgProbeFile.CondType = GetBefore("Rho Method:");
|
|
//hgProbeFile.RhoMethod = GetBefore("N N");
|
|
hgProbeFile.RhoMethod = GetBefore("N N");
|
|
ScanPast("Model :");
|
|
//hgProbeFile.Model = GetBefore("T T");
|
|
hgProbeFile.Model = GetBefore("T T");
|
|
ScanPast("Navg :");
|
|
hgProbeFile.NAvgMean = GetToken();
|
|
hgProbeFile.NAvgStdDev = GetToken();
|
|
hgProbeFile.NAvgRadialGradient = GetToken();
|
|
ScanPast("Nsl :");
|
|
hgProbeFile.NslMean = GetToken();
|
|
hgProbeFile.NslStdDev = GetToken();
|
|
hgProbeFile.NslRadialGradient = GetToken();
|
|
ScanPast("Vd :");
|
|
hgProbeFile.VdMean = GetToken();
|
|
hgProbeFile.VdStdDev = GetToken();
|
|
hgProbeFile.VdRadialGradient = GetToken();
|
|
ScanPast("Flat Z:");
|
|
hgProbeFile.FlatZMean = GetToken();
|
|
hgProbeFile.FlatZStdDev = GetToken();
|
|
hgProbeFile.FlatZRadialGradient = GetToken();
|
|
ScanPast("Rhoavg:");
|
|
hgProbeFile.RhoAvgMean = GetToken();
|
|
hgProbeFile.RhoAvgStdDev = GetToken();
|
|
hgProbeFile.RhoAvgRadialGradient = GetToken();
|
|
ScanPast("Rhosl :");
|
|
hgProbeFile.RhoslMean = GetToken();
|
|
hgProbeFile.RhoslStdDev = GetToken();
|
|
hgProbeFile.RhoslRadialGradient = GetToken();
|
|
ScanPast("Phase :");
|
|
hgProbeFile.PhaseMean = GetToken();
|
|
hgProbeFile.PhaseStdDev = GetToken();
|
|
hgProbeFile.PhaseRadialGradient = GetToken();
|
|
ScanPast("Grade :");
|
|
hgProbeFile.GradeMean = GetToken();
|
|
hgProbeFile.GradeStdDev = GetToken();
|
|
hgProbeFile.GradeRadialGradient = GetToken();
|
|
ScanPast("Rs :");
|
|
hgProbeFile.RsMean = GetToken();
|
|
hgProbeFile.RsStdDev = GetToken();
|
|
hgProbeFile.RsRadialGradient = GetToken();
|
|
|
|
string lot = hgProbeFile.Lot;
|
|
string[] segments = lot.Split('-');
|
|
|
|
if (segments.Length >= 1)
|
|
hgProbeFile.Reactor = segments[0];
|
|
|
|
if (segments.Length >= 2)
|
|
hgProbeFile.RDS = segments[1];
|
|
|
|
if (segments.Length >= 3)
|
|
{
|
|
string str = segments[2];
|
|
string[] segmentsB = str.Split('.');
|
|
if (segmentsB.Length >= 1)
|
|
hgProbeFile.PSN = segmentsB[0];
|
|
if (segmentsB.Length >= 2)
|
|
hgProbeFile.Layer = segmentsB[1];
|
|
}
|
|
if (segments.Length >= 4)
|
|
hgProbeFile.Zone = segments[3];
|
|
|
|
//ScanPast("Flat Z: Grade : % Flat Z: Grade : % Flat Z: Grade : %");
|
|
ScanPast("Flat Z: Grade : % Flat Z: Grade : % Flat Z: Grade : %");
|
|
string token = GetToken();
|
|
while (!string.IsNullOrEmpty(token))
|
|
{
|
|
HgProbeDetail hgProbeDetail = new HgProbeDetail { NAvg = token };
|
|
GetToEOL();
|
|
hgProbeDetail.Nsl = GetToken();
|
|
GetToEOL();
|
|
hgProbeDetail.Vd = GetToken();
|
|
GetToEOL();
|
|
hgProbeDetail.FlatZ = GetToken();
|
|
GetToEOL();
|
|
hgProbeDetail.RhoAvg = GetToken();
|
|
GetToEOL();
|
|
hgProbeDetail.Rhosl = GetToken();
|
|
GetToEOL();
|
|
hgProbeDetail.Phase = GetToken();
|
|
GetToEOL();
|
|
hgProbeDetail.Grade = GetToken();
|
|
hgProbeDetail.UniqueId = string.Concat("_Point-", hgProbeDetails.Count + 1);
|
|
hgProbeDetails.Add(hgProbeDetail);
|
|
GetToken();
|
|
GetToken();
|
|
GetToken();
|
|
GetToken();
|
|
token = GetToken();
|
|
//if (token.Contains("LincPDF") || token.Contains("MULTIPLE"))
|
|
if (token.Contains("MULTIPLE"))
|
|
{
|
|
//ScanPast("Flat Z: Grade : % Flat Z: Grade : % Flat Z: Grade : %");
|
|
//ScanPast("Flat Z: Grade : % Flat Z: Grade : % Flat Z: Grade : %");
|
|
ScanPast("Flat Z: Grade : % Flat Z: Grade : % Flat Z: Grade : %");
|
|
ScanPast("Flat Z: Grade : % Flat Z: Grade : % Flat Z: Grade : %");
|
|
token = GetToken();
|
|
}
|
|
}
|
|
}
|
|
hgProbeFile.UniqueId = string.Format("{0}_{1}_{2}", logic.Logistics.JobID, hgProbeFile.Lot, Path.GetFileNameWithoutExtension(logic.Logistics.ReportFullPath));
|
|
foreach (HgProbeDetail detail in hgProbeDetails)
|
|
{
|
|
detail.HeaderUniqueId = hgProbeFile.UniqueId;
|
|
detail.UniqueId = string.Concat(detail, detail.UniqueId);
|
|
}
|
|
fileInfoCollection.Add(new FileInfo(logic.Logistics.ReportFullPath));
|
|
result = new Tuple<HgProbeFile, List<HgProbeDetail>>(hgProbeFile, hgProbeDetails);
|
|
return result;
|
|
}
|
|
|
|
}
|
|
|
|
} |