348 lines
16 KiB
C#
348 lines
16 KiB
C#
using Adaptation.Shared;
|
|
using Adaptation.Shared.Metrology;
|
|
using Adaptation.Shared.Properties;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
|
|
namespace Adaptation.FileHandlers.OpenInsightMetrologyViewer;
|
|
|
|
public class WSRequest
|
|
{
|
|
|
|
public int Id { get; set; }
|
|
public string AreaCountAvg { get; set; }
|
|
public string AreaCountMax { get; set; }
|
|
public string AreaCountMin { get; set; }
|
|
public string AreaCountStdDev { get; set; }
|
|
public string AreaTotalAvg { get; set; }
|
|
public string AreaTotalMax { get; set; }
|
|
public string AreaTotalMin { get; set; }
|
|
public string AreaTotalStdDev { get; set; }
|
|
public string Date { get; set; }
|
|
public string HazeAverageAvg { get; set; }
|
|
public string HazeAverageMax { get; set; }
|
|
public string HazeAverageMin { get; set; }
|
|
public string HazeAverageStdDev { get; set; }
|
|
public string HazeRegionAvg { get; set; }
|
|
public string HazeRegionMax { get; set; }
|
|
public string HazeRegionMin { get; set; }
|
|
public string HazeRegionStdDev { get; set; }
|
|
public string Layer { get; set; }
|
|
public string LotID { get; set; }
|
|
public string LPDCM2Avg { get; set; }
|
|
public string LPDCM2Max { get; set; }
|
|
public string LPDCM2Min { get; set; }
|
|
public string LPDCM2StdDev { get; set; }
|
|
public string LPDCountAvg { get; set; }
|
|
public string LPDCountMax { get; set; }
|
|
public string LPDCountMin { get; set; }
|
|
public string LPDCountStdDev { get; set; }
|
|
public string Operator { get; set; }
|
|
public string ParseErrorText { get; set; }
|
|
public string PSN { get; set; }
|
|
public string RDS { get; set; }
|
|
public string Reactor { get; set; }
|
|
public string Recipe { get; set; }
|
|
public string ScratchCountAvg { get; set; }
|
|
public string ScratchCountMax { get; set; }
|
|
public string ScratchCountMin { get; set; }
|
|
public string ScratchCountStdDev { get; set; }
|
|
public string ScratchTotalAvg { get; set; }
|
|
public string ScratchTotalMax { get; set; }
|
|
public string ScratchTotalMin { get; set; }
|
|
public string ScratchTotalStdDev { get; set; }
|
|
public string SumOfDefectsAvg { get; set; }
|
|
public string SumOfDefectsMax { get; set; }
|
|
public string SumOfDefectsMin { get; set; }
|
|
public string SumOfDefectsStdDev { get; set; }
|
|
public string Title { get; set; }
|
|
public string UniqueId { get; set; }
|
|
public string Zone { get; set; }
|
|
|
|
public string CellName { get; set; }
|
|
public string Data { get; set; }
|
|
#pragma warning disable IDE1006
|
|
public int i { get; set; }
|
|
public List<pcl.Detail> Details { get; protected set; }
|
|
|
|
[Obsolete("For json")] public WSRequest() { }
|
|
|
|
#pragma warning disable IDE0060
|
|
internal WSRequest(IFileRead fileRead, Logistics logistics, List<pcl.Description> descriptions, string processDataStandardFormat = null)
|
|
#pragma warning restore IDE0060
|
|
{
|
|
i = -1;
|
|
Id = -1;
|
|
Zone = null;
|
|
Layer = null;
|
|
Title = null;
|
|
Data = "*Data*";
|
|
Details = new List<pcl.Detail>();
|
|
CellName = logistics.MesEntity;
|
|
pcl.Description x = descriptions[0];
|
|
//Header
|
|
{
|
|
AreaCountAvg = x.AreaCountAvg;
|
|
AreaCountMax = x.AreaCountMax;
|
|
AreaCountMin = x.AreaCountMin;
|
|
AreaCountStdDev = x.AreaCountStdDev;
|
|
AreaTotalAvg = x.AreaTotalAvg;
|
|
AreaTotalMax = x.AreaTotalMax;
|
|
AreaTotalMin = x.AreaTotalMin;
|
|
AreaTotalStdDev = x.AreaTotalStdDev;
|
|
Date = x.Date;
|
|
HazeAverageAvg = x.HazeAverageAvg;
|
|
HazeAverageMax = x.HazeAverageMax;
|
|
HazeAverageMin = x.HazeAverageMin;
|
|
HazeAverageStdDev = x.HazeAverageStdDev;
|
|
HazeRegionAvg = x.HazeRegionAvg;
|
|
HazeRegionMax = x.HazeRegionMax;
|
|
HazeRegionMin = x.HazeRegionMin;
|
|
HazeRegionStdDev = x.HazeRegionStdDev;
|
|
LotID = x.Lot;
|
|
LPDCM2Avg = x.LPDCM2Avg;
|
|
LPDCM2Max = x.LPDCM2Max;
|
|
LPDCM2Min = x.LPDCM2Min;
|
|
LPDCM2StdDev = x.LPDCM2StdDev;
|
|
LPDCountAvg = x.LPDCountAvg;
|
|
LPDCountMax = x.LPDCountMax;
|
|
LPDCountMin = x.LPDCountMin;
|
|
LPDCountStdDev = x.LPDCountStdDev;
|
|
ParseErrorText = x.ParseErrorText;
|
|
PSN = x.PSN;
|
|
RDS = x.RDS;
|
|
Reactor = x.Reactor;
|
|
Recipe = x.Recipe;
|
|
Operator = x.Employee;
|
|
ScratchCountAvg = x.ScratchCountAvg;
|
|
ScratchCountMax = x.ScratchCountMax;
|
|
ScratchCountMin = x.ScratchCountMin;
|
|
ScratchCountStdDev = x.ScratchCountStdDev;
|
|
ScratchTotalAvg = x.ScratchTotalAvg;
|
|
ScratchTotalMax = x.ScratchTotalMax;
|
|
ScratchTotalMin = x.ScratchTotalMin;
|
|
ScratchTotalStdDev = x.ScratchTotalStdDev;
|
|
SumOfDefectsAvg = x.SumOfDefectsAvg;
|
|
SumOfDefectsMax = x.SumOfDefectsMax;
|
|
SumOfDefectsMin = x.SumOfDefectsMin;
|
|
SumOfDefectsStdDev = x.SumOfDefectsStdDev;
|
|
UniqueId = x.UniqueId;
|
|
}
|
|
pcl.Detail detail;
|
|
foreach (pcl.Description description in descriptions)
|
|
{
|
|
detail = new pcl.Detail
|
|
{
|
|
Data = "*Data*",
|
|
i = -1,
|
|
Id = 0, //item.Id,
|
|
AreaCount = description.AreaCount,
|
|
AreaTotal = description.AreaTotal,
|
|
Bin1 = description.Bin1,
|
|
Bin2 = description.Bin2,
|
|
Bin3 = description.Bin3,
|
|
Bin4 = description.Bin4,
|
|
Bin5 = description.Bin5,
|
|
Bin6 = description.Bin6,
|
|
Bin7 = description.Bin7,
|
|
Bin8 = description.Bin8,
|
|
Comments = description.Comments,
|
|
Date = description.Date,
|
|
Diameter = description.Diameter,
|
|
Exclusion = description.Exclusion,
|
|
Gain = description.Gain,
|
|
HazeAverage = description.HazeAverage,
|
|
HazePeak = description.HazePeak,
|
|
HazeRegion = description.HazeRegion,
|
|
HazeRng = description.HazeRng,
|
|
HeaderUniqueId = description.HeaderUniqueId,
|
|
LPDCM2 = description.LPDCM2,
|
|
LPDCount = description.LPDCount,
|
|
Laser = description.Laser,
|
|
Mean = description.Mean,
|
|
Recipe = description.Recipe,
|
|
ScratchCount = description.ScratchCount,
|
|
ScratchTotal = description.ScratchTotal,
|
|
Slot = description.Slot,
|
|
Sort = description.Sort,
|
|
StdDev = description.StdDev,
|
|
SumOfDefects = description.SumOfDefects,
|
|
Thresh = description.Thresh,
|
|
Thruput = description.Thruput,
|
|
Title = null,
|
|
UniqueId = description.UniqueId
|
|
};
|
|
Details.Add(detail);
|
|
}
|
|
Date = logistics.DateTimeFromSequence.ToString();
|
|
if (UniqueId is null && Details.Count != 0)
|
|
UniqueId = Details[0].HeaderUniqueId;
|
|
for (int i = 0; i < Details.Count; i++)
|
|
{
|
|
if (string.IsNullOrEmpty(Details[i].Bin1))
|
|
Details[i].Bin1 = null;
|
|
if (string.IsNullOrEmpty(Details[i].Bin2))
|
|
Details[i].Bin2 = null;
|
|
if (string.IsNullOrEmpty(Details[i].Bin3))
|
|
Details[i].Bin3 = null;
|
|
if (string.IsNullOrEmpty(Details[i].Bin4))
|
|
Details[i].Bin4 = null;
|
|
if (string.IsNullOrEmpty(Details[i].Bin5))
|
|
Details[i].Bin5 = null;
|
|
if (string.IsNullOrEmpty(Details[i].Bin6))
|
|
Details[i].Bin6 = null;
|
|
if (string.IsNullOrEmpty(Details[i].Bin7))
|
|
Details[i].Bin7 = null;
|
|
if (string.IsNullOrEmpty(Details[i].Bin8))
|
|
Details[i].Bin8 = null;
|
|
}
|
|
UniqueId = $"{logistics.JobID}_{logistics.MID}_{logistics.DateTimeFromSequence:yyyyMMddHHmmssffff}";
|
|
for (int i = 0; i < Details.Count; i++)
|
|
{
|
|
Details[i].HeaderUniqueId = UniqueId;
|
|
Details[i].UniqueId = $"{logistics.JobID}_{logistics.MID}_{logistics.DateTimeFromSequence:yyyyMMddHHmmssffff}_Item-{i + 1}";
|
|
}
|
|
}
|
|
|
|
private static void UpdateDataPDF(List<pcl.Description> descriptions, string checkFileName)
|
|
{
|
|
string value;
|
|
string fullName;
|
|
object possiblePage;
|
|
object possibleString;
|
|
object possibleCOSArray;
|
|
java.util.List tokenList;
|
|
java.util.List arrayList;
|
|
java.io.OutputStream outputStream;
|
|
List<string> updateValues = new();
|
|
StringBuilder stringBuilder = new();
|
|
java.util.ListIterator tokenIterator;
|
|
java.util.ListIterator arrayIterator;
|
|
java.io.File file = new(checkFileName);
|
|
string reactorLoadLock = descriptions[0].Comments;
|
|
org.apache.pdfbox.pdmodel.common.PDStream pdStream;
|
|
org.apache.pdfbox.pdmodel.common.PDStream updatedStream;
|
|
org.apache.pdfbox.pdfparser.PDFStreamParser pdfStreamParser;
|
|
org.apache.pdfbox.pdfwriter.ContentStreamWriter contentStreamWriter;
|
|
org.apache.pdfbox.pdmodel.PDDocument pdDocument = org.apache.pdfbox.pdmodel.PDDocument.load(file);
|
|
org.apache.pdfbox.pdmodel.PDDocumentCatalog pdDocumentCatalog = pdDocument.getDocumentCatalog();
|
|
java.util.List pagesList = pdDocumentCatalog.getAllPages();
|
|
java.util.ListIterator pageIterator = pagesList.listIterator();
|
|
if (string.IsNullOrEmpty(descriptions[0].Lot) || string.IsNullOrEmpty(descriptions[0].Reactor) || descriptions[0].Lot.StartsWith(descriptions[0].Reactor))
|
|
fullName = string.Empty;
|
|
else
|
|
fullName = $"{descriptions[0].Reactor}-{descriptions[0].RDS}-{descriptions[0].PSN} ";
|
|
for (short i = 1; i < short.MaxValue; i++)
|
|
{
|
|
if (!pageIterator.hasNext())
|
|
break;
|
|
possiblePage = pageIterator.next();
|
|
if (possiblePage is not org.apache.pdfbox.pdmodel.PDPage page)
|
|
continue;
|
|
pdStream = page.getContents();
|
|
pdfStreamParser = new org.apache.pdfbox.pdfparser.PDFStreamParser(pdStream);
|
|
pdfStreamParser.parse();
|
|
tokenList = pdfStreamParser.getTokens();
|
|
tokenIterator = tokenList.listIterator();
|
|
for (short t = 1; i < short.MaxValue; t++)
|
|
{
|
|
if (!tokenIterator.hasNext())
|
|
break;
|
|
possibleCOSArray = tokenIterator.next();
|
|
if (possibleCOSArray is not org.apache.pdfbox.cos.COSArray cossArray)
|
|
continue;
|
|
_ = stringBuilder.Clear();
|
|
arrayList = cossArray.toList();
|
|
arrayIterator = arrayList.listIterator();
|
|
for (short a = 1; i < short.MaxValue; a++)
|
|
{
|
|
if (!arrayIterator.hasNext())
|
|
break;
|
|
possibleString = arrayIterator.next();
|
|
if (possibleString is not org.apache.pdfbox.cos.COSString cossString)
|
|
continue;
|
|
value = cossString.getString();
|
|
_ = stringBuilder.Append(value);
|
|
if (value != "]")
|
|
continue;
|
|
updateValues.Add(value);
|
|
value = stringBuilder.ToString();
|
|
if (value.Contains("[]"))
|
|
cossArray.setString(a - 1, string.Concat("*", fullName, reactorLoadLock, "]"));
|
|
else
|
|
cossArray.setString(a - 1, string.Concat(" {*", fullName, reactorLoadLock, "}]"));
|
|
}
|
|
}
|
|
if (updateValues.Count != 0)
|
|
{
|
|
updatedStream = new org.apache.pdfbox.pdmodel.common.PDStream(pdDocument);
|
|
outputStream = updatedStream.createOutputStream();
|
|
contentStreamWriter = new org.apache.pdfbox.pdfwriter.ContentStreamWriter(outputStream);
|
|
contentStreamWriter.writeTokens(tokenList);
|
|
outputStream.close();
|
|
page.setContents(updatedStream);
|
|
}
|
|
}
|
|
if (updateValues.Count != 0)
|
|
pdDocument.save(checkFileName);
|
|
pdDocument.close();
|
|
}
|
|
|
|
internal static long GetHeaderId(IFileRead fileRead, Logistics logistics, string openInsightMetrologyViewerAPI, string openInsightMetrologyViewerFileShare, int weekOfYear, WS.Results results, List<pcl.Description> descriptions)
|
|
{
|
|
long result;
|
|
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}");
|
|
(_, 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;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
#pragma warning disable IDE0060
|
|
internal static void PostOpenInsightMetrologyViewerAttachments(IFileRead fileRead, Logistics logistics, string openInsightMetrologyViewerAPI, List<pcl.Description> descriptions, string matchDirectory, WS.Results results, string headerIdDirectory)
|
|
#pragma warning restore IDE0060
|
|
{
|
|
string checkFileName;
|
|
pcl.Description description;
|
|
string[] pclFiles = Directory.GetFiles(matchDirectory, "*.pcl", SearchOption.TopDirectoryOnly);
|
|
if (pclFiles.Length != 1)
|
|
throw new Exception($"Invalid source file count for <{results.HeaderId}>!");
|
|
string sourceFileNameNoExt = Path.GetFileNameWithoutExtension(pclFiles[0]);
|
|
List<WS.Attachment> dataAttachments = new();
|
|
List<WS.Attachment> headerAttachments = new();
|
|
checkFileName = Path.Combine(matchDirectory, $"{sourceFileNameNoExt}_data.pdf");
|
|
if (!File.Exists(checkFileName))
|
|
throw new Exception("Header file doesn't exist!");
|
|
else
|
|
{
|
|
UpdateDataPDF(descriptions, checkFileName);
|
|
headerAttachments.Add(new WS.Attachment(results, headerIdDirectory, $"{logistics.JobID}_{logistics.MID}_{logistics.DateTimeFromSequence:yyyyMMddHHmmssffff}", "Data.pdf", checkFileName));
|
|
}
|
|
for (int i = 0; i < descriptions.Count; i++)
|
|
{
|
|
description = descriptions[i];
|
|
checkFileName = Path.Combine(matchDirectory, $"{sourceFileNameNoExt}_s{description.Slot}_image.pdf");
|
|
if (File.Exists(checkFileName))
|
|
dataAttachments.Add(new WS.Attachment(results, headerIdDirectory, $"{logistics.JobID}_{logistics.MID}_{logistics.DateTimeFromSequence:yyyyMMddHHmmssffff}_Item-{i + 1}", "Image.pdf", checkFileName));
|
|
else
|
|
{
|
|
checkFileName = Path.Combine(matchDirectory, $"{sourceFileNameNoExt}_s{description.Slot}_data.pdf");
|
|
if (File.Exists(checkFileName))
|
|
dataAttachments.Add(new WS.Attachment(results, headerIdDirectory, $"{logistics.JobID}_{logistics.MID}_{logistics.DateTimeFromSequence:yyyyMMddHHmmssffff}_Item-{i + 1}", "Image.pdf", checkFileName));
|
|
}
|
|
}
|
|
if (dataAttachments.Count == 0 || dataAttachments.Count != descriptions.Count)
|
|
throw new Exception($"Invalid attachment count! {dataAttachments.Count} != {descriptions.Count}");
|
|
WS.AttachFiles(openInsightMetrologyViewerAPI, headerAttachments, dataAttachments);
|
|
}
|
|
|
|
} |