diff --git a/.vscode/launch.json b/.vscode/launch.json index 3e3e421..f9d952c 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -11,6 +11,26 @@ "preLaunchTask": "build", "program": "${workspaceFolder}/bin/Debug/net8.0/win-x64/File-Folder-Helper.dll", "args": [ + "s", + "X", + "D:/ProgramData/EC_Characterization_Si/Dummy/DEP08CEPIEPSILON/PollPath", + "Day-Helper-2025-07-01", + "*.pdsf", + "987654321", + "Time", + ".json", + "id12~CenterTemp,id13~CenterSetpt,id15~FrontTemp,id153~PPSTEPNAME,id154~SystemState,id16~FrontSetpt,id172~LVC1Ratio,id173~LVC1Carrier,id176~TotalWaferCount,i-d-1-7-8~TIME,id18~SideTemp,id183~SCRDrive4,id19~SideSetpt,id193~SCRLOAD4,id21~RearTemp,id22~RearSetpt,id221~LeftDefaultRecipe,id222~RightDefaultRecipe,id223~RecipeCompleteMsg,id25~N2H2Setpt,id26~N2H2Flow,id27~HCLSetpt,id28~HCLFlow,id29~HCLHISetpt,id30~HCLHIFlow,id37~NSRCSetpt,id38~NSRCFlow,id39~NDILSetpt,id40~NDILFlow,id41~NINJSetpt,id42~NINJFlow,id57~LVC1Setpt,id58~LVC1Flow,id61~ROTSetpt,id62~ROTSpeed,id78~LL1State,id79~LL1Init,id80~LL1Lotid,id81~LL1WafersIn,id82~LL1WfrCnt,id83~LL2State,id84~LL2Init,id85~LL2Lotid,id86~LL2WafersIn,id87~LL2WfrCnt,id93~ProcessState,vp93~ProcessState,vp154~SystemState,vp78~LL1State,vp83~LL2State,vp176~TotalWaferCount,vp80~LL1Lotid,vp85~LL2Lotid,vp153~PPSTEPNAME,vp221~LeftDefaultRecipe,vp222~RightDefaultRecipe,vp223~RecipeCompleteMsg", + "D:/ProgramData/EC_Characterization_Si/Dummy/DEP08CEPIEPSILON/JavaScriptObjectNotation", + "D:/ProgramData/EC_Characterization_Si/Dummy/DEP08CEPIEPSILON/Markdown", + "D:/ProgramData/EC_Characterization_Si/Dummy/DEP08CEPIEPSILON/KeyValuePairs", + "654321", + "s", + "s", + "X", + "D:/ProgramData/EC_Characterization_Si/Dummy/DEP08CEPIEPSILON/R55", + "Day-Helper-2023-11-30", + "yyMMddhhmmssfff", + "\"vp154\"", "s", "X", "V:/Tmp/Phares/Pictures/2023 TI2023.6 Fall Samsung", @@ -21,18 +41,6 @@ "0.259594,0.460161,0.1642,0.279605~0.45477,0.489035,0.195175,0.32383~0.328993,0.446263,0.0379464,0.0459656", "9", "x-825511723~x-444522128~831410304", - "s", - "X", - "\\\\mesfs.infineon.com\\EC_APC\\Production\\Traces\\DEP08CEPIEPSILON\\PollPath", - "Day-Helper-2025-07-01", - "*.pdsf", - "654321", - "Time", - "id12~CenterTemp,id13~CenterSetpt,id15~FrontTemp,id153~PPSTEPNAME,id154~SystemState,id16~FrontSetpt,id172~LVC1Ratio,id173~LVC1Carrier,id176~TotalWaferCount,i-d-1-7-8~TIME,id18~SideTemp,id183~SCRDrive4,id19~SideSetpt,id193~SCRLOAD4,id21~RearTemp,id22~RearSetpt,id221~LeftDefaultRecipe,id222~RightDefaultRecipe,id223~RecipeCompleteMsg,id25~N2H2Setpt,id26~N2H2Flow,id27~HCLSetpt,id28~HCLFlow,id29~HCLHISetpt,id30~HCLHIFlow,id37~NSRCSetpt,id38~NSRCFlow,id39~NDILSetpt,id40~NDILFlow,id41~NINJSetpt,id42~NINJFlow,id57~LVC1Setpt,id58~LVC1Flow,id61~ROTSetpt,id62~ROTSpeed,id78~LL1State,id79~LL1Init,id80~LL1Lotid,id81~LL1WafersIn,id82~LL1WfrCnt,id83~LL2State,id84~LL2Init,id85~LL2Lotid,id86~LL2WafersIn,id87~LL2WfrCnt,id93~ProcessState", - "\\\\mesfs.infineon.com\\EC_APC\\Production\\Traces\\DEP08CEPIEPSILON\\Markdown", - "\\\\mesfs.infineon.com\\EC_APC\\Production\\Traces\\DEP08CEPIEPSILON\\KeyValuePairs", - "\\\\mesfs.infineon.com\\EC_APC\\Production\\Traces\\DEP08CEPIEPSILON\\JavaScriptObjectNotation", - "s", "X", "F:/0-ISO-A", "Day-Helper-2025-06-28", diff --git a/ADO2025/PI6/Helper-2025-07-01.cs b/ADO2025/PI6/Helper-2025-07-01.cs index a474eb2..0e623eb 100644 --- a/ADO2025/PI6/Helper-2025-07-01.cs +++ b/ADO2025/PI6/Helper-2025-07-01.cs @@ -14,6 +14,11 @@ internal static partial class Helper20250701 { internal partial class JsonElementSourceGenerationContext : JsonSerializerContext { } + [JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)] + [JsonSerializable(typeof(ReadOnlyDictionary>))] + internal partial class ReadOnlyDictionaryStringReadOnlyDictionaryStringStringSourceGenerationContext : JsonSerializerContext { + } + internal static void ProcessDataStandardFormatTo(ILogger logger, List args) { logger.LogInformation(args[0]); logger.LogInformation(args[1]); @@ -22,24 +27,27 @@ internal static partial class Helper20250701 { logger.LogInformation(args[4]); logger.LogInformation(args[5]); logger.LogInformation(args[6]); + logger.LogInformation(args[7]); string[] segments; + string extension = args[5]; string timeColumn = args[4]; string searchPattern = args[2]; int sizeFilter = int.Parse(args[3]); - string[] columns = args[5].Split(','); + string[] columns = args[6].Split(','); Dictionary columnMapping = []; string sourceDirectory = Path.GetFullPath(args[0].Split('~')[0]); - string destinationDirectory = Path.GetFullPath(args[6].Split('~')[0]); + string destinationDirectory = Path.GetFullPath(args[7].Split('~')[0]); foreach (string column in columns) { segments = column.Split('~'); columnMapping.Add(segments[0], segments[1]); } string[] directories = Directory.GetDirectories(sourceDirectory, "*", SearchOption.TopDirectoryOnly); - ProcessDataStandardFormatTo(logger, sourceDirectory, searchPattern, sizeFilter, timeColumn, columnMapping, destinationDirectory, directories); + ProcessDataStandardFormatTo(logger, sourceDirectory, searchPattern, sizeFilter, timeColumn, extension, columnMapping, destinationDirectory, directories); Helpers.HelperDeleteEmptyDirectories.DeleteEmptyDirectories(logger, sourceDirectory); } - private static void ProcessDataStandardFormatTo(ILogger logger, string sourceDirectory, string searchPattern, int sizeFilter, string timeColumn, Dictionary columnMapping, string destinationDirectory, string[] directories) { + private static void ProcessDataStandardFormatTo(ILogger logger, string sourceDirectory, string searchPattern, int sizeFilter, string timeColumn, string extension, Dictionary columnMapping, string destinationDirectory, string[] directories) { + string text; string? json; string[] files; string markdown; @@ -51,7 +59,7 @@ internal static partial class Helper20250701 { string directoryName; string checkDirectory; foreach (string directory in directories) { - if (Path.GetFileName(directory).Contains('-')) { + if (sizeFilter < 987654321 && Path.GetFileName(directory).Contains('-')) { continue; } files = Directory.GetFiles(directory, searchPattern, SearchOption.TopDirectoryOnly); @@ -77,35 +85,43 @@ internal static partial class Helper20250701 { if (!Directory.Exists(checkDirectory)) { _ = Directory.CreateDirectory(checkDirectory); } - checkFile = Path.Combine(checkDirectory, $"{fileInfo.Name}.md"); + checkFile = Path.Combine(checkDirectory, $"{fileInfo.Name}{extension}"); if (File.Exists(checkFile)) { continue; } - collections = GetMarkdown(logger, timeColumn, columnMapping, file, fileInfo.Name); - if (string.IsNullOrEmpty(collections)) { - logger.LogWarning("collections is null"); + if (extension == ".md") { + collections = GetMarkdown(logger, timeColumn, columnMapping, file, fileInfo.Name); + if (string.IsNullOrEmpty(collections)) { + logger.LogWarning("collections is null"); + continue; + } + text = collections; + } else if (extension == ".pipe.md") { + json = GetJavaScriptObjectNotation(logger, file); + if (string.IsNullOrEmpty(json)) { + logger.LogWarning("json is null"); + continue; + } + pipeTable = GetPipeTable(logger, json); + if (string.IsNullOrEmpty(pipeTable)) { + logger.LogWarning("pipeTable is null"); + continue; + } + markdown = $"# {fileInfo.Name}{Environment.NewLine}{Environment.NewLine}{pipeTable}{Environment.NewLine}"; + text = markdown; + } else if (extension == ".json") { + json = GetJavaScriptObjectNotation(logger, file); + if (string.IsNullOrEmpty(json)) { + logger.LogWarning("json is null"); + continue; + } + text = json; + } else { + logger.LogWarning("{extension} is not mapped!", extension); continue; } - File.WriteAllText(checkFile, collections); + File.WriteAllText(checkFile, text); File.SetLastWriteTime(checkFile, fileInfo.LastAccessTime); - if (!string.IsNullOrEmpty(destinationDirectory)) { - continue; - } - json = GetJavaScriptObjectNotation(logger, file); - if (string.IsNullOrEmpty(json)) { - logger.LogWarning("json is null"); - continue; - } - File.WriteAllText($"{checkFile}.md", json); - File.SetLastWriteTime($"{checkFile}.md", fileInfo.LastAccessTime); - pipeTable = GetPipeTable(logger, json); - if (string.IsNullOrEmpty(pipeTable)) { - logger.LogWarning("pipeTable is null"); - continue; - } - markdown = $"# {fileInfo.Name}{Environment.NewLine}{Environment.NewLine}{pipeTable}{Environment.NewLine}"; - File.WriteAllText($"{checkFile}.md", markdown); - File.SetLastWriteTime($"{checkFile}.md", fileInfo.LastAccessTime); logger.LogInformation("<{checkFile}> was written", checkFile); } } @@ -239,42 +255,139 @@ internal static partial class Helper20250701 { if (lines.Length < columnTitlesLine.Value + 1) { logger.LogWarning("<{lines}>(s)", lines.Length); } else { - result = GetJavaScriptObjectNotation(columnTitlesLine.Value, [], lines); + result = GetJavaScriptObjectNotation(columnTitlesLine.Value, lines); } } return result; } - private static string GetJavaScriptObjectNotation(int columnTitlesLine, string[] columns, string[] lines) { + private static string GetJavaScriptObjectNotation(int columnTitlesLine, string[] lines) { #pragma warning disable CA1845, IDE0057 - string result = "[\n"; - string line; + string result; + string record; string value; string[] segments; - if (columns.Length == 0) { - columns = lines[columnTitlesLine].Split('\t'); - } + string? json = null; + List records = []; + ReadOnlyCollection? footerLines = null; + string[] columns = lines[columnTitlesLine].Split('\t'); for (int i = columnTitlesLine + 1; i < lines.Length; i++) { if (lines[i].StartsWith("NUM_DATA_ROWS")) { + footerLines = GetFooterLines(lines, i); break; } - line = "{"; + record = "{"; segments = lines[i].Split('\t'); if (segments.Length > columns.Length) { continue; } for (int c = 0; c < segments.Length; c++) { value = segments[c].Replace("\\", "\\\\").Replace("\"", "\\\""); - line += '"' + columns[c].Trim('"') + '"' + ':' + '"' + value + '"' + ','; + record += string.Concat('"', columns[c].Trim('"'), '"', ':', '"', value, '"', ','); } - line = line.Substring(0, line.Length - 1) + '}' + ',' + '\n'; - result += line; + record = string.Concat(record.Substring(0, record.Length - 1), '}'); + records.Add(record); } - result = result.Substring(0, result.Length - 2) + ']'; + if (footerLines is not null && footerLines.Count > 0) { + ReadOnlyDictionary footerKeyValuePairs = GetFooterKeyValuePairs(footerLines); + ReadOnlyDictionary> logisticKeyValuePairs = GetLogisticKeyValuePairs(footerLines, footerKeyValuePairs); + json = JsonSerializer.Serialize(logisticKeyValuePairs, ReadOnlyDictionaryStringReadOnlyDictionaryStringStringSourceGenerationContext.Default.ReadOnlyDictionaryStringReadOnlyDictionaryStringString); + } + string footerText = string.IsNullOrEmpty(json) || json == "{}" ? string.Empty : $",{Environment.NewLine}\"PDSF\":{Environment.NewLine}{json}"; + result = string.Concat( + '{', + Environment.NewLine, + '"', + "Count", + '"', + ": ", + records.Count, + ',', + Environment.NewLine, + '"', + "Records", + '"', + ": ", + Environment.NewLine, + '[', + Environment.NewLine, + string.Join($",{Environment.NewLine}", records), + Environment.NewLine, + ']', + footerText, + '}'); return result; #pragma warning restore CA1845, IDE0057 } + private static ReadOnlyCollection GetFooterLines(string[] lines, int i) { + List results = []; + for (int j = i; j < lines.Length; j++) { + results.Add(lines[j]); + if (lines[j].StartsWith("END_HEADER")) + break; + } + return results.AsReadOnly(); + } + + private static ReadOnlyDictionary GetFooterKeyValuePairs(ReadOnlyCollection footerLines) { + Dictionary results = []; + string[] segments; + foreach (string footerLine in footerLines) { + segments = footerLine.Split('\t'); + if (segments.Length != 2 || string.IsNullOrEmpty(segments[1].Trim())) { + continue; + } + if (segments[1].Contains(';')) { + continue; + } else { + results.Add(segments[0], segments[1]); + } + } + return results.AsReadOnly(); + } + + private static ReadOnlyDictionary> GetLogisticKeyValuePairs(ReadOnlyCollection footerLines, ReadOnlyDictionary footerKeyValuePairs) { + Dictionary> results = []; + string[] segments; + string[] subSegments; + string[] subSubSegments; + Dictionary? keyValue; + results.Add("Footer", footerKeyValuePairs); + Dictionary> keyValuePairs = []; + foreach (string footerLine in footerLines) { + segments = footerLine.Split('\t'); + if (segments.Length != 2 || string.IsNullOrEmpty(segments[1].Trim())) { + continue; + } + if (!segments[1].Contains(';') || !segments[1].Contains('=')) { + continue; + } else { + subSegments = segments[1].Split(';'); + if (subSegments.Length < 1) { + continue; + } + if (!keyValuePairs.TryGetValue(segments[0], out keyValue)) { + keyValuePairs.Add(segments[0], []); + if (!keyValuePairs.TryGetValue(segments[0], out keyValue)) { + throw new Exception(); + } + } + foreach (string segment in subSegments) { + subSubSegments = segment.Split('='); + if (subSubSegments.Length != 2) { + continue; + } + keyValue.Add(subSubSegments[0], subSubSegments[1]); + } + } + } + foreach (KeyValuePair> keyValuePair in keyValuePairs) { + results.Add(keyValuePair.Key, keyValuePair.Value.AsReadOnly()); + } + return results.AsReadOnly(); + } + private static string? GetPipeTable(ILogger logger, string json) { string? result = null; string? value; @@ -310,4 +423,5 @@ internal static partial class Helper20250701 { } return result; } + } \ No newline at end of file diff --git a/Day/Q42023/Helper-2023-11-30.cs b/Day/Q42023/Helper-2023-11-30.cs index b71468e..f82072d 100644 --- a/Day/Q42023/Helper-2023-11-30.cs +++ b/Day/Q42023/Helper-2023-11-30.cs @@ -65,7 +65,7 @@ internal static class Helper20231130 return result; } - private static ReadOnlyCollection GetSystemStateValues(List lines, string[] columns, int keyColumnIndex, ReadOnlyDictionary systemStates) + private static ReadOnlyCollection GetSystemStateValues(List lines, string[] columns, int keyColumnIndex, ReadOnlyDictionary systemStateToNames) { List results = []; string[] values; @@ -79,7 +79,7 @@ internal static class Helper20231130 keyColumnValue = values[keyColumnIndex]; if (string.IsNullOrEmpty(keyColumnValue)) continue; - if (!systemStates.TryGetValue(keyColumnValue, out systemState)) + if (!systemStateToNames.TryGetValue(keyColumnValue, out systemState)) continue; if (results.Contains(systemState)) continue; @@ -106,7 +106,7 @@ internal static class Helper20231130 string missingKeyDirectory = Path.Combine(sourceDirectory, "Missing-Key"); if (!Directory.Exists(missingKeyDirectory)) _ = Directory.CreateDirectory(missingKeyDirectory); - ReadOnlyDictionary systemStates = GetSystemStates(); + ReadOnlyDictionary systemStateToNames = GetSystemStates(); ReadOnlyCollection records = GetRecords(sourceDirectory, timestampFormat); foreach (Record record in records) { @@ -132,7 +132,7 @@ internal static class Helper20231130 continue; } logger.LogInformation("{timestamp} triggered", record.TimeStamp); - systemStateValues = GetSystemStateValues(lines, columns, keyColumnIndex.Value, systemStates); + systemStateValues = GetSystemStateValues(lines, columns, keyColumnIndex.Value, systemStateToNames); if (systemStateValues.Count == 0) { File.Move(record.File, Path.Combine(sourceDirectory, missingKeyDirectory, record.FileName)); @@ -142,7 +142,6 @@ internal static class Helper20231130 systemState = string.Join('-', systemStateValues); checkFileName = Path.Combine(Path.GetDirectoryName(record.File) ?? throw new Exception(), $"{record.Equipment}-{record.TimeStamp}-{systemState}.pdsf"); File.WriteAllLines(checkFileName, lines); - File.Delete(record.File); if (DateTime.TryParseExact(record.TimeStamp, timestampFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) File.SetLastWriteTime(checkFileName, dateTime); }