From b29ef7682de752f2ff2e61777ab5b1870892b6da Mon Sep 17 00:00:00 2001 From: "phares@iscn5cg20977xq" Date: Fri, 24 Oct 2025 22:33:26 -0700 Subject: [PATCH] Add CombineFiles functionality for Day-Helper-2025-10-22 and update related configurations --- .vscode/launch.json | 221 +------------------------------ .vscode/tasks.json | 14 ++ ADO2025/PI7/Helper-2025-10-22.cs | 136 +++++++++++++++++++ Day/HelperDay.cs | 2 + File-Folder-Helper.csproj | 2 +- 5 files changed, 156 insertions(+), 219 deletions(-) create mode 100644 ADO2025/PI7/Helper-2025-10-22.cs diff --git a/.vscode/launch.json b/.vscode/launch.json index 11cd240..6504022 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -11,96 +11,12 @@ "preLaunchTask": "Build", "program": "${workspaceFolder}/bin/Debug/net8.0/win-x64/File-Folder-Helper.dll", "args": [ - "s", - "X", - "J:/5-Other-Small/Kanban/Year-Season/2025/2025-0.Winter/1736201197030", - "Day-Helper-2024-06-23", - "*.md", - "##_Sub-tasks", - "-_[code-insiders](", - "index.md", - "-_[,](", - "##_Done", - ".kan", - "J:/5-Other-Small/Kanban/Year-Season", - "316940400000", - "J:/5-Other-Small/Kanban-mestsa003/{}", - "s", - "X", - "X:/Production/Logs/EAF-Warn-Error-002-014-004~X:/Production/Logs/EAF-Info-Warn-002-059-000~X:/Production/Logs/EAF-Info-Warn-002-060-000~X:/Production/Logs/EAF-Info-Warn-002-061-001", - "Day-Helper-2025-09-26", - "EAF_INFO*.lo*~EAF_WARN*.lo*", - "S1F4 W-Bit", - "yyyy-MM-dd HH:mm:ss,fff", - "0", - "10", - "EAF_INFO*.lo*~EAF_WARN*.lo*", - "DF_Error*.lo*~DF_Notification*.lo*~DF_Unit*.lo*", - "2025-*.log", - "X:/Production/Logs/EAF-Warn-Error-002-014-004~X:/Production/Logs/EAF-Info-Warn-002-059-000~X:/Production/Logs/EAF-Info-Warn-002-060-000~X:/Production/Logs/EAF-Info-Warn-002-061-001", - "X:/Production/Logs/EDA_004_016_001~X:/Production/Logs/EDA_004_021_000", - "s", - "X", - "A:/6-Other-Large-Z/Linux-Ubuntu-Affirm/etc/nginx/include~B:/6-Other-Large-Z/Linux-Ubuntu-BCHS/etc/nginx/include~J:/6-Other-Large-Z/Linux-Ubuntu-JMLC/etc/nginx/include~P:/6-Other-Large-Z/Linux-Ubuntu-Phares/etc/nginx/include", - "Day-Helper-2025-09-08", - "*.conf", - "/etc/nginx/include/", - "server_name", - "proxy_pass~root", - "oauth2", - "s", - "X", - "P:/6-Other-Large-Z/Current-Results/A2)People/c9dbce3b/([])/File-Folder-Helper/638443643487798783/638443643487798783", - "Day-Helper-2024-05-18", - "people.json", - "person", - "ownerId,name,birthDate", - "c76905af-c06a-4a78-a9a7-c32f5b58e793", - "yyyy-MM-dd", - "1900-01-01", - "s", - "X", - "P:/1-Images-A/Images-0b793904", - "Day-Helper-2025-07-26", - "4e+9", - "L:/Git/AA/Rename/.vscode/.UserSecrets/secrets.json", - ".avif~.bmp~.gif~.heic~.insp~.jp2~.jpe~.jpeg~.jpg~.jxl~.png~.psd~.raw~.rw2~.svg~.tif~.tiff~.webp~.3gp~.3gpp~.avi~.dvr-ms~.flv~.insv~.m2t~.m2ts~.m4v~.mkv~.mov~.mp4~.mpe~.mpeg~.mpg~.mts~.ts~.webm~.wmv", - "P:/6-Other-Large-Z/Current-Results/C)Resize/0b793904/Original", - "(helper)", - "s", - "X", - "P:/1-Images-A/Images-0b793904", - "Day-Helper-2024-12-17", - ".job.json", - "thumbs.db~sync.ffs_db~verify.json~.html", - "I:/0-ISO-A", - "D:/5-Other-Small/Disk/Snap2HTML/Snap2HTML.exe", - "s", - "X", - "P:/Tmp/Phares/Helper-2025-07-20", - "Day-Helper-2025-07-20", - "871467010009.jpg", - "L:/Git/AA/Rename/.vscode/.UserSecrets/secrets.json", - "A:/()/638432064000000000.51/1401-08-03_02/2023/X+441981864000000000/871467010009.444090906.jpg.png", - "*.png", - "D:/{}/DisneyWorld 2019/Magic Kingdom/871467010009.jpg.xmp", - "*.xmp", - "{}-output", - "s", - "X", - "D:/ProgramData/EC_Characterization_Si/Dummy/DEP08CEPIEPSILON/Log", - "Day-Helper-2025-07-10", - "R*", - "EAF_INFO*", "s", "X", "D:/ProgramData/EC_Characterization_Si/Dummy/DEP08CEPIEPSILON/JavaScriptObjectNotation", - "Day-Helper-2025-07-09", + "Day-Helper-2025-10-22", "*.json", - "987654321", - ".agg", - "id93,vp93,ProcessState,id154,vp154,SystemState,id78,vp78,LL1State,id83,vp83,LL2State,id176,vp176,TotalWaferCount,id80,vp80,LL1Lotid,id85,vp85,LL2Lotid,id153,vp153,PPSTEPNAME,id221,vp221,LeftDefaultRecipe,id222,vp222,RightDefaultRecipe,id223,vp223,RecipeCompleteMsg", - "D:/ProgramData/EC_Characterization_Si/Dummy/DEP08CEPIEPSILON/Reactor", + "D:/ProgramData/EC_Characterization_Si/Dummy/DEP08CEPIEPSILON/WorkWeek", "s", "X", "D:/ProgramData/EC_Characterization_Si/Dummy/DEP08CEPIEPSILON/PollPath", @@ -114,138 +30,7 @@ "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", - "P:/Tmp/Phares/Pictures/2023 TI2023.6 Fall Samsung", - "Day-Helper-2025-07-05", - "x-653889110721.jpg~401223300869.jpg", - "3648,2736,1~3024,4032,6", - "0.341694,0.599963,0.1642,0.279605~0.552357,0.65095,0.195175,0.32383~0.31002,0.42328,0.0379464,0.0459656", - "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", - "X", - "F:/0-ISO-A", - "Day-Helper-2025-06-28", - "*.iso", - "F", - "s", - "X", - "D:/5-Other-Small", - "Day-Helper-2024-12-17", - ".job.json", - "thumbs.db~sync.ffs_db~verify.json~.html", - "D:/0-ISO-A", - "D:/5-Other-Small/Proxmox/Snap2HTML/Snap2HTML.exe", - "s", - "M", - "D:/5-Other-Small/Notes/EC-Documentation", - "-d", - "D:/5-Other-Small/Notes/EC-Documentation/.vscode/helper", - "s", - "X", - "D:/5-Other-Small/Proxmox/DiskInfo", - "Day-Helper-2025-06-18", - "*.json", - "D:/5-Other-Small/Proxmox/Disk-Info-Old", - "-2025-", - "1", - "s", - "X", - "D:/Tmp", - "Day-Helper-2025-06-02", - "infineon\\MESPhares", - "BACKLOG~BIORAD2~BIORAD3~BIORAD4~BIORAD5~CDE4~CDE5~CDE6~DEP08CEPIEPSILON~DEP08SIASM~DEP08SIHTRPLC~EC~HGCV1~HGCV2~HGCV3~MESAFIBACKLOG~MET06AWCT~MET08ANLYSDIFAAST230~MET08AWCT~MET08DDUPSFS6420~MET08DDUPSP1TBI~MET08RESIHGCV~MET08RESIMAPCDE~MET08RESISRP2100~MET08THFTIRQS408M~MET08THFTIRSTRATUS~METCLIMATEC~R29~R32~R36~R47~R55~R57~R61~R62~R65~R70~R72~R73~R74~R75~R77~SP101~SPV01~SRP~TENCOR1~TENCOR2~TENCOR3~TRENDLOG~WC6INCH1~WC6INCH2~WC6INCH3~WC6INCH4~WC8INCH1~WC8INCH2~WC8INCH3", - "s", - "X", - "D:/5-Other-Small/Proxmox/ffnm", - "Day-Helper-2025-05-21", - "*.pdf", - "*.md", - "2", - "MM-dd-yy", - "Trans Date~Effective Date~Description~Withdrawal Deposit~Balance", - "s", - "X", - "D:/Tmp/phares/VisualStudioCode", - "Day-Helper-2025-05-19", - "D:/Tmp/phares/VisualStudioCode/.vscode/input.json", - "s", - "X", - "D:/Tmp/phares/VisualStudioCode", - "Day-Helper-2025-05-19", - "D:/Tmp/phares/VisualStudioCodeLeft", - "z-include-patterns.nsv", - "z-exclude-patterns.nsv", - "http://localhost:5004", - "/api/SyncV1/?", - ",L", - ".G", - "+~G~~L~+~Custom-Default", - "", - "+~G~~G~-~Mirror", - "+~G~~~~Update", - "+~G~~L~+~Custom-Default", - "-~G~~G~+~Custom-A", - "-~L~~L~+~Custom-B", - "+~L~~L~-~Custom-C", - "s", - "X", - "\\\\mesfs.infineon.com\\EC_Characterization_Si\\Archive\\BIORAD4\\2025_Week_16\\2025-04-17", - "Day-Helper-2025-02-19", - "csv-*.pdsf", - "*.pdsf", - "Time,HeaderUniqueId,UniqueId,Date,Wafer,Position,BIORAD4", - ",BIORAD4", - ",BIORAD4", - "Test|EventId,Date|DateTime,Position|Slot,DeltaThicknessSlotsOneAndTwentyFive|Actual Delta Thick Pts 1 and 25,PercentDeltaThicknessSlotsOneAndTwentyFive|% Delta Thick Pts 1 and 25,MID|Cassette,Lot|Batch,Title|Batch,Wafer|Text,Thickness|Site,MeanThickness|GradeMean,|BIORAD4", - "Time,A_LOGISTICS,B_LOGISTICS,Test,Count,Index,MesEntity,MID,Date,Employee,Lot,PSN,Reactor,Recipe,Cassette,GradeStdDev,HeaderUniqueId,Layer,MeanThickness,PassFail,RDS,Slot,Title,UniqueId,Wafer,Zone,Mean,Position,StdDev,Thickness,ThicknessSlotOne,ThicknessSlotTwentyFive,DeltaThicknessSlotsOneAndTwentyFive,PercentDeltaThicknessSlotsOneAndTwentyFive", - "Time,A_LOGISTICS,B_LOGISTICS,Count,Sequence,MesEntity,Index,Batch,Cassette,DateTime,Destination,Mean,PassFail,Recipe,Reference,Site,Slot,Source,StdDev,Text,GradeMean,GradeStdDev,RDS,PSN,Reactor,Layer,Zone,Employee,InferredLot,Thickness First Slot,Thickness Last Slot,Actual Delta Thick Pts 1 and 25,% Delta Thick Pts 1 and 25,EventId", - "0,1,2,31,3,6,5,8,9,27,7,23,24,13,8,21,-1,25,20,12,22,16,7,-1,19,26,11,16,18,15,-1,-1,29,30", - "s", - "X", - "C:/Users/phares/AppData/Roaming/FreeFileSync", - "Day-Helper-2025-04-21", - "GlobalSettings.xml", - "LastSync|Config", - "s", - "X", - "L:/Tmp/MET08ANLYSDIFAAST230", - "Day-Helper-2025-03-06", - "*.pdsf", - "s", - "X", - "D:/ProgramData/VisualStudioCode|D:/6-Other-Large-Z/Linux-Ubuntu-Phares/home/lphares/dorico", - "Day-Helper-2025-04-07", - "z-include-patterns.nsv", - "z-exclude-patterns.nsv", - "https://isccvm57294f1ed/VisualStudioCode|hxttps://dorico.phares.duckdns.org|hxttps://mestsa006.infineon.com/VisualStudioCode", - "+|G|G|G|-", - "||||", - "666", - "777", - "888", - "999", - "s", - "X", - "C:/Users/PHARES/AppData/Local/IFXApps/gatus", - "Day-Helper-2025-04-04", - "*.json", - ".metrics", - "https://messa010ec.infineon.com/metrics", - "gatus_results_endpoint_success", - "666", - "777", - "888", - "999", - "" + ".json" ], "cwd": "${workspaceFolder}", "console": "integratedTerminal", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 302fc46..bd873a9 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -348,6 +348,20 @@ "label": "File-Folder-Helper AOT s X Day-Helper-2025-03-20", "problemMatcher": [], "type": "shell" + }, + { + "args": [ + "s", + "X", + "D:/ProgramData/EC_Characterization_Si/Dummy/DEP08CEPIEPSILON/JavaScriptObjectNotation", + "Day-Helper-2025-10-22", + "*.json", + "D:/ProgramData/EC_Characterization_Si/Dummy/DEP08CEPIEPSILON/WorkWeek" + ], + "command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe", + "label": "File-Folder-Helper AOT s X Day-Helper-2025-10-22", + "problemMatcher": [], + "type": "shell" } ], "version": "2.0.0" diff --git a/ADO2025/PI7/Helper-2025-10-22.cs b/ADO2025/PI7/Helper-2025-10-22.cs new file mode 100644 index 0000000..528871b --- /dev/null +++ b/ADO2025/PI7/Helper-2025-10-22.cs @@ -0,0 +1,136 @@ +using Microsoft.Extensions.Logging; +using System.Collections.ObjectModel; +using System.Globalization; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace File_Folder_Helper.ADO2025.PI7; + +internal static partial class Helper20251022 { + + private record Root(int Count, JsonElement[] Records, ProcessDataStandardFormat? ProcessDataStandardFormat) { + + internal static Root? Get(string file) { + Root? result; + string? json = File.ReadAllText(file); + result = JsonSerializer.Deserialize(json, Helper20251022RootSourceGenerationContext.Default.Root); + if (result is null || result.ProcessDataStandardFormat is null || result.Records.Length == 0) { + result = null; + } + return result; + } + + } + + [JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)] + [JsonSerializable(typeof(Root))] + private partial class Helper20251022RootSourceGenerationContext : JsonSerializerContext { + } + + [JsonSourceGenerationOptions(WriteIndented = false, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)] + [JsonSerializable(typeof(JsonElement))] + private partial class Helper20251022JsonElementSourceGenerationContext : JsonSerializerContext { + } + + private record ProcessDataStandardFormat([property: JsonPropertyName("Footer")] JsonElement? Footer, [property: JsonPropertyName("LOGISTICS_1")] JsonElement? Logistics); + + internal static void CombineFiles(ILogger logger, List args) { + logger.LogInformation(args[0]); + logger.LogInformation(args[1]); + logger.LogInformation(args[2]); + logger.LogInformation(args[3]); + string searchPattern = args[2]; + string sourceDirectory = Path.GetFullPath(args[0].Split('~')[0]); + string destinationDirectory = Path.GetFullPath(args[3].Split('~')[0]); + string[] directories = Directory.GetDirectories(sourceDirectory, "*", SearchOption.TopDirectoryOnly); + ReadOnlyDictionary> files = GetFiles(logger, searchPattern, directories.AsReadOnly()); + CombineFiles(logger, destinationDirectory, files); + } + + private static ReadOnlyDictionary> GetFiles(ILogger logger, string searchPattern, ReadOnlyCollection directories) { + Dictionary> results = []; + string key; + string[] files; + FileInfo fileInfo; + string[] segments; + string weekOfYear; + Calendar calendar = new CultureInfo("en-US").Calendar; + List? collection; + foreach (string directory in directories) { + files = Directory.GetFiles(directory, searchPattern, SearchOption.TopDirectoryOnly); + files = files.OrderBy(l => l).ThenBy(l => l.Length).ToArray(); + for (int i = 0; i < files.Length; i++) { + fileInfo = new(files[i]); + segments = fileInfo.Name.Split('_'); + if (segments.Length < 2) { + logger.LogWarning("{fileInfoName} does not have enough segments!", fileInfo.Name); + continue; + } + weekOfYear = $"{fileInfo.LastWriteTime.Year}_Week_{calendar.GetWeekOfYear(fileInfo.LastWriteTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday):00}"; + key = $"{segments[0]}_{weekOfYear}"; + if (!results.TryGetValue(key, out collection)) { + collection = []; + results.Add(key, collection); + } + collection.Add(files[i]); + } + } + return results.AsReadOnly(); + } + + private static void CombineFiles(ILogger logger, string destinationDirectory, ReadOnlyDictionary> files) { + Root? root; + string json; + string[] lines; + string fileName; + string? jsonFooter; + string? jsonLogistics; + JsonElement jsonElementB; + List segments = []; + List jsonLines = []; + if (!Directory.Exists(destinationDirectory)) { + _ = Directory.CreateDirectory(destinationDirectory); + } + foreach (KeyValuePair> keyValuePair in files) { + jsonLines.Clear(); + fileName = Path.Combine(destinationDirectory, $"{keyValuePair.Key}.json"); + foreach (string file in keyValuePair.Value) { + root = Root.Get(file); + if (root is null) { + logger.LogWarning("result is null"); + continue; + } + foreach (JsonElement jsonElement in root.Records) { + jsonFooter = root.ProcessDataStandardFormat?.Footer?.ToString(); + jsonLogistics = root.ProcessDataStandardFormat?.Logistics?.ToString(); + if (string.IsNullOrEmpty(jsonFooter) && string.IsNullOrEmpty(jsonLogistics)) { + jsonLines.Add(jsonElement.ToString()); + } else { + segments.Clear(); + segments.Add(jsonElement.ToString()[..^1]); + if (!string.IsNullOrEmpty(jsonFooter)) { + segments.Add(","); + lines = jsonFooter[1..^1].Split(Environment.NewLine); + segments.AddRange(lines.Select(l => l.Trim())); + } + if (!string.IsNullOrEmpty(jsonLogistics)) { + segments.Add(","); + lines = jsonLogistics[1..^1].Split(Environment.NewLine); + segments.AddRange(lines.Select(l => l.Trim())); + } + segments.Add("}"); + jsonElementB = JsonSerializer.Deserialize(string.Join(' ', segments), Helper20251022JsonElementSourceGenerationContext.Default.JsonElement); + jsonLines.Add(jsonElementB.ToString()); + } + } + } + if (jsonLines.Count == 0) { + logger.LogWarning("jsonLines is empty"); + continue; + } + json = string.Concat('[', Environment.NewLine, string.Join($",{Environment.NewLine}", jsonLines), Environment.NewLine, ']'); + File.WriteAllText(fileName, json); + } + } + +} \ No newline at end of file diff --git a/Day/HelperDay.cs b/Day/HelperDay.cs index b4d5aa1..7385742 100644 --- a/Day/HelperDay.cs +++ b/Day/HelperDay.cs @@ -189,6 +189,8 @@ internal static class HelperDay ADO2025.PI7.Helper20250908.DebugProxyPass(logger, args); else if (args[1] == "Day-Helper-2025-09-26") ADO2025.PI7.Helper20250926.RenameThenFindFirstAndLast(logger, args); + else if (args[1] == "Day-Helper-2025-10-22") + ADO2025.PI7.Helper20251022.CombineFiles(logger, args); else throw new Exception(appSettings.Company); } diff --git a/File-Folder-Helper.csproj b/File-Folder-Helper.csproj index ebf0771..53f5596 100644 --- a/File-Folder-Helper.csproj +++ b/File-Folder-Helper.csproj @@ -18,7 +18,7 @@ - +