Compare commits

..

12 Commits

21 changed files with 2903 additions and 302 deletions

1
.gitignore vendored
View File

@ -336,3 +336,4 @@ ASALocalRun/
.extensions-vscode-oss
.extensions-vscode-insiders
.vscode/.UserSecrets/secrets.json
.vscode/.helper

View File

@ -0,0 +1,4 @@
@host = eaf-prod.mes.infineon.com:9003
POST {{host}}/StatusQuery
Accept: application/json

290
.vscode/launch.json vendored
View File

@ -1,106 +1,188 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/bin/Debug/net8.0/win-x64/File-Folder-Helper.dll",
"args": [
"s",
"X",
"D:/5-Other-Small/Proxmox/ffnm",
"Day-Helper-2025-05-21",
"*.pdf",
"*.md",
"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",
""
],
"cwd": "${workspaceFolder}",
"console": "integratedTerminal",
"stopAtEntry": false
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach"
},
{
"type": "node",
"request": "launch",
"name": "node Launch Current Opened File",
"program": "${file}"
}
]
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/bin/Debug/net8.0/win-x64/File-Folder-Helper.dll",
"args": [
"s",
"X",
"V:/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",
"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",
"*.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",
""
],
"cwd": "${workspaceFolder}",
"console": "integratedTerminal",
"stopAtEntry": false
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach"
},
{
"type": "node",
"request": "launch",
"name": "node Launch Current Opened File",
"program": "${file}"
},
{
"type": "bun",
"internalConsoleOptions": "neverOpen",
"request": "launch",
"name": "Debug File",
"program": "${file}",
"cwd": "${workspaceFolder}",
"stopOnEntry": false,
"watchMode": false
},
{
"type": "bun",
"internalConsoleOptions": "neverOpen",
"request": "launch",
"name": "Run File",
"program": "${file}",
"cwd": "${workspaceFolder}",
"noDebug": true,
"watchMode": false
}
]
}

34
.vscode/mklink.md vendored
View File

@ -14,18 +14,28 @@ mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.kanbn" "D:\5-Other-Small\Kanban
mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.kanbn" "D:\5-Other-Small\Kanban\File-Folder-Helper"
```
```bash
del "L:\DevOps\Mesa_FI\File-Folder-Helper\.extensions-vscode"
del "L:\DevOps\Mesa_FI\File-Folder-Helper\.extensions-vscode-oss"
del "L:\DevOps\Mesa_FI\File-Folder-Helper\.extensions-vscode-insiders"
mkdir "C:\Users\phares\.vscode\extensions\ifx.type-script-helper-1.111.0\net8.0\win-x64\publish"
mkdir "C:\Users\phares\.vscode-oss\extensions\ifx.type-script-helper-1.111.0\net8.0\win-x64\publish"
mkdir "C:\Users\phares\.vscode-insiders\extensions\ifx.type-script-helper-1.111.0\net8.0\win-x64\publish"
mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.extensions-vscode" "C:\Users\phares\.vscode\extensions\ifx.type-script-helper-1.111.0"
mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.extensions-vscode-oss" "C:\Users\phares\.vscode-oss\extensions\ifx.type-script-helper-1.111.0"
mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.extensions-vscode-insiders" "C:\Users\phares\.vscode-insiders\extensions\ifx.type-script-helper-1.111.0"
```
```bash Thu Jul 18 2024 13:47:40 GMT-0700 (Mountain Standard Time)
mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.vscode\.UserSecrets" "C:\Users\phares\AppData\Roaming\Microsoft\UserSecrets\8da397d4-13ec-4576-9722-3c79cad25563"
```
```bash 1749414316830 = 638850111168300000 = 2025-2.Spring = Sun Jun 08 2025 13:25:16 GMT-0700 (Mountain Standard Time)
C:\Users\PHARES\.vscode\extensions\infineon-technologies-ag-mesa-fi.infineon-technologies-ag-mesa-fi-cost-of-delay-helper-1.124.0
del "L:\DevOps\Mesa_FI\File-Folder-Helper\.extensions-vscode"
del "L:\DevOps\Mesa_FI\File-Folder-Helper\.extensions-vscode-oss"
del "L:\DevOps\Mesa_FI\File-Folder-Helper\.extensions-vscode-insiders"
mkdir "C:\Users\phares\.vscode\extensions\infineon-technologies-ag-mesa-fi.infineon-technologies-ag-mesa-fi-cost-of-delay-helper-1.124.0\net8.0\win-x64"
mkdir "C:\Users\phares\.vscode-oss\extensions\infineon-technologies-ag-mesa-fi.infineon-technologies-ag-mesa-fi-cost-of-delay-helper-1.124.0\net8.0\win-x64"
mkdir "C:\Users\phares\.vscode-insiders\extensions\infineon-technologies-ag-mesa-fi.infineon-technologies-ag-mesa-fi-cost-of-delay-helper-1.124.0\net8.0\win-x64"
mklink /J "C:\Users\phares\.vscode\extensions\infineon-technologies-ag-mesa-fi.infineon-technologies-ag-mesa-fi-cost-of-delay-helper-1.124.0\net8.0\win-x64\publish" "L:\DevOps\Mesa_FI\File-Folder-Helper\bin\Release\net8.0\win-x64\publish"
mklink /J "C:\Users\phares\.vscode-oss\extensions\infineon-technologies-ag-mesa-fi.infineon-technologies-ag-mesa-fi-cost-of-delay-helper-1.124.0\net8.0\win-x64\publish" "L:\DevOps\Mesa_FI\File-Folder-Helper\bin\Release\net8.0\win-x64\publish"
mklink /J "C:\Users\phares\.vscode-insiders\extensions\infineon-technologies-ag-mesa-fi.infineon-technologies-ag-mesa-fi-cost-of-delay-helper-1.124.0\net8.0\win-x64\publish" "L:\DevOps\Mesa_FI\File-Folder-Helper\bin\Release\net8.0\win-x64\publish"
```
```bash 1749957317559 = 638855541175590000 = 2025-2.Spring = Sat Jun 14 2025 20:15:17 GMT-0700 (Mountain Standard Time)
mkdir "L:\DevOps\MESA_FI\file-folder-helper\bin\Release\net8.0\win-x64"
mklink /J "L:\DevOps\MESA_FI\file-folder-helper\bin\Release\net8.0\win-x64\publish" "D:\5-Other-Small\Proxmox\publish"
```
```bash 1750459968132 = 638860567681320000 = 2025-3.Summer = Fri Jun 20 2025 15:52:47 GMT-0700 (Mountain Standard Time)
mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.vscode\.helper" "D:\5-Other-Small\Notes\Infineon\.vscode\helper"
```

View File

@ -10,6 +10,8 @@
"**/node_modules": true
},
"cSpell.words": [
"abcdefghiklmnopqrstuvwxyz",
"Acks",
"ASPNETCORE",
"BIORAD",
"BIRT",
@ -21,6 +23,7 @@
"FAMS",
"Gatus",
"GIVN",
"HGCV",
"HUSB",
"Immich",
"INDI",
@ -31,6 +34,7 @@
"Linc",
"mesfs",
"mestsa",
"netrm",
"NpgSql",
"NSFX",
"OBJE",
@ -44,9 +48,11 @@
"Reparse",
"Rijndael",
"Serilog",
"startable",
"SUBM",
"SURN",
"SYSLIB",
"TENCOR",
"VSTS",
"WIQL",
"WSJF"

View File

@ -24,9 +24,12 @@ internal static partial class Helper20241217
long Length,
string RelativePath);
private record Record(string Directory,
private record Record(string DestinationDirectory,
string DirectoryName,
Job Job,
string Path);
string Path,
string Snap2HyperTextMarkupLanguage,
string SourceDirectory);
private record Job(string? AlternatePath,
string Directory,
@ -49,47 +52,69 @@ internal static partial class Helper20241217
{
}
private static ReadOnlyCollection<File> GetFiles(string searchPattern, string[] ignoreFileNames, Record record) =>
GetFiles(record.SourceDirectory, searchPattern, ignoreFileNames);
internal static void Backup(ILogger<Worker> logger, List<string> args)
{
Job jobNew;
string path;
string? json;
string fileName;
bool areTheyTheSame;
string directoryName;
IEnumerable<Record> records;
logger.LogInformation(args[0]);
logger.LogInformation(args[1]);
logger.LogInformation(args[2]);
logger.LogInformation(args[3]);
logger.LogInformation(args[4]);
ReadOnlyCollection<File> files;
string searchPattern = args[2];
IEnumerable<string> searchPatternFiles;
string[] ignoreFileNames = args[3].Split('~');
string destination = Path.GetFullPath(args[4]);
string sourceDirectory = Path.GetFullPath(args[0]);
char destinationDriveLetter = args[4].Split(':')[0][0];
string? snap2HyperTextMarkupLanguage = args.Count < 6 ? null : Path.GetFullPath(args[5]);
logger.LogInformation("Searching <{sourceDirectory}> with search pattern {searchPattern}", args[0], searchPattern);
if (Debugger.IsAttached)
Verify(searchPattern, ignoreFileNames);
IEnumerable<Record> records = GetRecords(sourceDirectory, searchPattern);
foreach (Record record in records)
for (int i = 1; i < 3; i++)
{
if (record.Job is null || string.IsNullOrEmpty(record.Job.Extension))
continue;
logger.LogInformation("Searching <{directory}>", record.Directory);
files = GetFiles(searchPattern, ignoreFileNames, record);
jobNew = GetJob(searchPattern, ignoreFileNames, record, files);
json = JsonSerializer.Serialize(jobNew, JobSourceGenerationContext.Default.Job);
areTheyTheSame = GetAreTheyTheSame(logger, searchPattern, ignoreFileNames, record, jobNew);
if (areTheyTheSame)
if (i == 1)
{
WriteAllText(record.Path, json);
continue;
searchPatternFiles = Directory.EnumerateFiles(sourceDirectory, searchPattern, new EnumerationOptions { IgnoreInaccessible = true, RecurseSubdirectories = true });
}
else if (i == 2)
{
searchPatternFiles = Directory.GetFiles(sourceDirectory, searchPattern, SearchOption.AllDirectories);
}
else
throw new NotImplementedException();
records = GetRecords(sourceDirectory, destination, searchPatternFiles);
foreach (Record record in records)
{
if (record.Job is null || string.IsNullOrEmpty(record.Job.Extension))
continue;
logger.LogInformation("Searching <{directory}>", record.SourceDirectory);
if (snap2HyperTextMarkupLanguage is not null && System.IO.File.Exists(snap2HyperTextMarkupLanguage))
WriteSnap2HyperTextMarkupLanguage(logger, snap2HyperTextMarkupLanguage, record);
files = GetFiles(searchPattern, ignoreFileNames, record);
jobNew = GetJob(searchPattern, ignoreFileNames, record, files);
json = JsonSerializer.Serialize(jobNew, JobSourceGenerationContext.Default.Job);
areTheyTheSame = GetAreTheyTheSame(logger, searchPattern, ignoreFileNames, record, jobNew);
if (areTheyTheSame)
{
WriteAllText(record.Path, json);
continue;
}
fileName = $"{record.DirectoryName}-{DateTime.Now:yyyy-MM-dd-HH-mm-ss-fff}{record.Job.Extension}";
path = Path.Combine(record.DestinationDirectory, fileName);
logger.LogInformation("Writing <{path}> extension", path);
WritePassedExtension(record, files, record.DirectoryName, path);
logger.LogInformation("Wrote <{path}> extension", path);
logger.LogInformation("Moved <{path}> extension", path);
WriteAllText(record, json, path);
}
directoryName = Path.GetFileName(record.Directory);
path = Path.Combine(record.Directory, $"{directoryName}-{DateTime.Now:yyyy-MM-dd-HH-mm-ss-fff}{record.Job.Extension}");
logger.LogInformation("Writing <{directory}> extension", record.Directory);
WritePassedExtension(destinationDriveLetter, record, files, path);
WriteAllText(record.Path, json);
}
if (Debugger.IsAttached && records.Count() == 0)
{
files = GetFiles(sourceDirectory, searchPattern, ignoreFileNames);
json = JsonSerializer.Serialize(files.ToArray(), FilesSourceGenerationContext.Default.FileArray);
WriteAllText(Path.Combine(Environment.CurrentDirectory, ".vscode", "helper", ".json"), json);
}
}
@ -138,24 +163,28 @@ internal static partial class Helper20241217
return results.AsReadOnly();
}
private static IEnumerable<Record> GetRecords(string directory, string searchPattern)
private static IEnumerable<Record> GetRecords(string directory, string destination, IEnumerable<string> files)
{
Job? job;
string json;
Record record;
string fileName;
string directoryName;
IEnumerable<string> files = Directory.EnumerateFiles(directory, searchPattern, new EnumerationOptions { IgnoreInaccessible = true, RecurseSubdirectories = true });
string sourceDirectory;
string destinationDirectory;
string snap2HyperTextMarkupLanguage;
foreach (string file in files)
{
fileName = Path.GetFileName(file);
directoryName = Path.GetDirectoryName(file) ?? throw new Exception();
sourceDirectory = Path.GetDirectoryName(file) ?? throw new Exception();
directoryName = Path.GetFileName(sourceDirectory);
if (!fileName.StartsWith('.'))
{
System.IO.File.Move(file, Path.Combine(directoryName, $".{fileName}"));
System.IO.File.Move(file, Path.Combine(sourceDirectory, $".{fileName}"));
continue;
}
json = System.IO.File.ReadAllText(file);
snap2HyperTextMarkupLanguage = Path.Combine(sourceDirectory, ".html");
if (string.IsNullOrEmpty(json) || json is "{}" or "[]")
job = null;
else
@ -168,11 +197,36 @@ internal static partial class Helper20241217
FilesTotalLength: 0,
Keep: 3,
Targets: []);
record = new(Directory: directoryName, Job: job, Path: file);
destinationDirectory = $"{destination}{sourceDirectory[2..]}";
if (!Directory.Exists(destinationDirectory))
_ = Directory.CreateDirectory(destinationDirectory);
record = new(DestinationDirectory: destinationDirectory,
DirectoryName: directoryName,
Job: job,
Path: file,
Snap2HyperTextMarkupLanguage: snap2HyperTextMarkupLanguage,
SourceDirectory: sourceDirectory);
yield return record;
}
}
private static void WriteSnap2HyperTextMarkupLanguage(ILogger<Worker> logger, string snap2HyperTextMarkupLanguage, Record record)
{
string title = Path.GetFileName(record.SourceDirectory);
ProcessStartInfo processStartInfo = new()
{
Arguments = $"-path:\"{record.SourceDirectory}\" -outfile:\"{record.Snap2HyperTextMarkupLanguage}\" -title:\"{title}\" -hidden -silent",
FileName = snap2HyperTextMarkupLanguage,
RedirectStandardError = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
WorkingDirectory = record.SourceDirectory
};
Process? process = Process.Start(processStartInfo) ?? throw new Exception("Process should not be null.");
process.WaitForExit();
logger.LogInformation($"Snap2HyperTextMarkupLanguage: {process.StandardOutput.ReadToEnd()}{Environment.NewLine}{process.StandardError.ReadToEnd()}{Environment.NewLine}{process.ExitCode}");
}
private static ReadOnlyCollection<File> GetFiles(string directory, string searchPattern, string[] ignoreFileNames)
{
List<File> results = [];
@ -197,16 +251,13 @@ internal static partial class Helper20241217
return results.AsReadOnly();
}
private static ReadOnlyCollection<File> GetFiles(string searchPattern, string[] ignoreFileNames, Record record) =>
GetFiles(record.Directory, searchPattern, ignoreFileNames);
private static Job GetJob(string searchPattern, string[] ignoreFileNames, Record record, ReadOnlyCollection<File> files)
{
Job result;
ReadOnlyCollection<File> collection = GetFilteredFiles(searchPattern, ignoreFileNames, files);
double filesTotalLengthNew = collection.Select(l => l.Length).Sum();
result = new(AlternatePath: record.Job.AlternatePath,
Directory: record.Directory,
Directory: record.SourceDirectory,
Extension: record.Job.Extension,
Files: collection.ToArray(),
FilesCount: collection.Count,
@ -225,7 +276,7 @@ internal static partial class Helper20241217
if (filesCountNew != filesCountOld)
{
result = false;
logger.LogInformation("<{directory}> file count has changed {filesCountNew} != {filesCountOld}", record.Directory, filesCountNew, filesCountOld);
logger.LogInformation("<{directory}> file count has changed {filesCountNew} != {filesCountOld}", record.SourceDirectory, filesCountNew, filesCountOld);
}
else
{
@ -234,7 +285,7 @@ internal static partial class Helper20241217
if (filesTotalLengthNew != filesTotalLengthOld)
{
result = false;
logger.LogInformation("<{directory}> file length has changed {filesTotalLengthNew} != {filesTotalLengthOld}", record.Directory, filesTotalLengthNew, filesTotalLengthOld);
logger.LogInformation("<{directory}> file length has changed {filesTotalLengthNew} != {filesTotalLengthOld}", record.SourceDirectory, filesTotalLengthNew, filesTotalLengthOld);
}
else
{
@ -245,9 +296,12 @@ internal static partial class Helper20241217
else
{
result = false;
WriteAllText(Path.Combine(Environment.CurrentDirectory, ".vscode", "helper", "old.json"), jsonOld);
WriteAllText(Path.Combine(Environment.CurrentDirectory, ".vscode", "helper", "new.json"), jsonNew);
logger.LogInformation("<{directory}> file serialized are different {filesTotalLengthNew} != {filesTotalLengthOld}", record.Directory, filesTotalLengthNew, filesTotalLengthOld);
if (Debugger.IsAttached)
{
WriteAllText(Path.Combine(Environment.CurrentDirectory, ".vscode", "helper", "old.json"), jsonOld);
WriteAllText(Path.Combine(Environment.CurrentDirectory, ".vscode", "helper", "new.json"), jsonNew);
}
logger.LogInformation("<{directory}> file serialized are different {filesTotalLengthNew} != {filesTotalLengthOld}", record.SourceDirectory, filesTotalLengthNew, filesTotalLengthOld);
}
}
}
@ -261,36 +315,27 @@ internal static partial class Helper20241217
System.IO.File.WriteAllText(path, text);
}
private static void WritePassedExtension(char destinationDriveLetter, Record record, ReadOnlyCollection<File> files, string path)
private static void WritePassedExtension(Record record, ReadOnlyCollection<File> files, string directoryName, string path)
{
string directoryName = Path.GetFileName(record.Directory);
if (record.Job.Extension.Equals(".iso", StringComparison.OrdinalIgnoreCase))
WriteISO(destinationDriveLetter, record, files, path, directoryName);
WriteISO(record, files, path, directoryName);
else if (record.Job.Extension.Equals(".zip", StringComparison.OrdinalIgnoreCase))
WriteZIP(destinationDriveLetter, record, files, path);
WriteZIP(record, files, path);
else
throw new NotImplementedException();
}
private static void WriteISO(char destinationDriveLetter, Record record, ReadOnlyCollection<File> files, string path, string directoryName)
private static void WriteISO(Record record, ReadOnlyCollection<File> files, string path, string directoryName)
{
string checkFile = $"{destinationDriveLetter}{path[1..]}";
string checkDirectory = Path.GetDirectoryName(checkFile) ?? throw new Exception();
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
CDBuilder builder = new() { UseJoliet = true, VolumeIdentifier = directoryName.Length < 25 ? directoryName : directoryName[..25] };
foreach (File file in files)
_ = builder.AddFile(file.RelativePath, Path.Combine(record.Directory, file.RelativePath));
builder.Build(checkFile);
_ = builder.AddFile(file.RelativePath, Path.Combine(record.SourceDirectory, file.RelativePath));
builder.Build(path);
}
private static void WriteZIP(char destinationDriveLetter, Record record, ReadOnlyCollection<File> files, string path)
private static void WriteZIP(Record record, ReadOnlyCollection<File> files, string path)
{
string checkFile = $"{destinationDriveLetter}{path[1..]}";
string checkDirectory = Path.GetDirectoryName(checkFile) ?? throw new Exception();
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
using ZipArchive zip = ZipFile.Open(checkFile, ZipArchiveMode.Create);
using ZipArchive zip = ZipFile.Open(path, ZipArchiveMode.Create);
string directoryEntry;
List<string> directoryEntries = [];
foreach (File file in files)
@ -302,7 +347,16 @@ internal static partial class Helper20241217
_ = zip.CreateEntry(file.RelativePath);
}
foreach (File file in files)
_ = zip.CreateEntryFromFile(Path.Combine(record.Directory, file.RelativePath), file.RelativePath);
_ = zip.CreateEntryFromFile(Path.Combine(record.SourceDirectory, file.RelativePath), file.RelativePath);
}
private static void WriteAllText(Record record, string text, string path)
{
WriteAllText(record.Path, text);
System.IO.File.Copy(record.Path, $"{path}.json");
string checkFile = Path.Combine(record.SourceDirectory, ".html");
if (System.IO.File.Exists(checkFile))
System.IO.File.Copy(checkFile, $"{path}.html");
}
}

View File

@ -277,12 +277,12 @@ internal static partial class Helper20250219 {
}
if (!lookForNumbers) {
for (int c = 0; c < segments.Length; c++) {
value = segments[c].Replace("\"", "\\\"").Replace("\\", "\\\\");
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("\\", "\\\\");
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))

View File

@ -71,7 +71,7 @@ internal static partial class Helper20250306 {
if (segments.Length != columnsLength)
continue;
for (int c = 1; c < segments.Length; c++) {
value = segments[c].Replace("\"", "\\\"").Replace("\\", "\\\\");
value = segments[c].Replace("\\", "\\\\").Replace("\"", "\\\"");
line += '"' + columns[c].Trim('"') + '"' + ':' + '"' + value + '"' + ',';
}
line = line.Substring(0, line.Length - 1) + '}' + ',' + '\n';

277
ADO2025/PI6/Envelope.cs Normal file
View File

@ -0,0 +1,277 @@
#nullable disable
#pragma warning disable CS8603
#pragma warning disable CS8632
#pragma warning disable IDE1006
namespace IFX.Shared.PasteSpecialXml.EAF.XML.API.Envelope;
// NOTE: Generated code may require at least .NET Framework 4.5 or .NET Core/Standard 2.0.
/// <remarks/>
[Serializable()]
[System.ComponentModel.DesignerCategory("code")]
[System.Xml.Serialization.XmlType(AnonymousType = true, Namespace = "http://www.w3.org/2003/05/soap-envelope")]
[System.Xml.Serialization.XmlRoot(Namespace = "http://www.w3.org/2003/05/soap-envelope", IsNullable = false)]
public partial class Envelope
{
private EnvelopeHeader? headerField;
private EnvelopeBody? bodyField;
/// <remarks/>
public EnvelopeHeader Header
{
get => this.headerField;
set => this.headerField = value;
}
/// <remarks/>
public EnvelopeBody Body
{
get => this.bodyField;
set => this.bodyField = value;
}
}
/// <remarks/>
[Serializable()]
[System.ComponentModel.DesignerCategory("code")]
[System.Xml.Serialization.XmlType(AnonymousType = true, Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public partial class EnvelopeHeader
{
private Sequence? sequenceField;
private SequenceAcknowledgement? sequenceAcknowledgementField;
private Action? actionField;
private string? relatesToField;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Namespace = "http://schemas.xmlsoap.org/ws/2005/02/rm")]
public Sequence Sequence
{
get => this.sequenceField;
set => this.sequenceField = value;
}
/// <remarks/>
[System.Xml.Serialization.XmlElement(Namespace = "http://schemas.xmlsoap.org/ws/2005/02/rm")]
public SequenceAcknowledgement SequenceAcknowledgement
{
get => this.sequenceAcknowledgementField;
set => this.sequenceAcknowledgementField = value;
}
/// <remarks/>
[System.Xml.Serialization.XmlElement(Namespace = "http://www.w3.org/2005/08/addressing")]
public Action Action
{
get => this.actionField;
set => this.actionField = value;
}
/// <remarks/>
[System.Xml.Serialization.XmlElement(Namespace = "http://www.w3.org/2005/08/addressing")]
public string RelatesTo
{
get => this.relatesToField;
set => this.relatesToField = value;
}
}
/// <remarks/>
[Serializable()]
[System.ComponentModel.DesignerCategory("code")]
[System.Xml.Serialization.XmlType(AnonymousType = true, Namespace = "http://schemas.xmlsoap.org/ws/2005/02/rm")]
[System.Xml.Serialization.XmlRoot(Namespace = "http://schemas.xmlsoap.org/ws/2005/02/rm", IsNullable = false)]
public partial class Sequence
{
private string? identifierField;
private byte messageNumberField;
private object? lastMessageField;
private byte mustUnderstandField;
/// <remarks/>
public string Identifier
{
get => this.identifierField;
set => this.identifierField = value;
}
/// <remarks/>
public byte MessageNumber
{
get => this.messageNumberField;
set => this.messageNumberField = value;
}
/// <remarks/>
public object LastMessage
{
get => this.lastMessageField;
set => this.lastMessageField = value;
}
/// <remarks/>
[System.Xml.Serialization.XmlAttribute(Form = System.Xml.Schema.XmlSchemaForm.Qualified, Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public byte mustUnderstand
{
get => this.mustUnderstandField;
set => this.mustUnderstandField = value;
}
}
/// <remarks/>
[Serializable()]
[System.ComponentModel.DesignerCategory("code")]
[System.Xml.Serialization.XmlType(AnonymousType = true, Namespace = "http://schemas.xmlsoap.org/ws/2005/02/rm")]
[System.Xml.Serialization.XmlRoot(Namespace = "http://schemas.xmlsoap.org/ws/2005/02/rm", IsNullable = false)]
public partial class SequenceAcknowledgement
{
private string? identifierField;
private SequenceAcknowledgementAcknowledgementRange? acknowledgementRangeField;
private byte bufferRemainingField;
/// <remarks/>
public string Identifier
{
get => this.identifierField;
set => this.identifierField = value;
}
/// <remarks/>
public SequenceAcknowledgementAcknowledgementRange AcknowledgementRange
{
get => this.acknowledgementRangeField;
set => this.acknowledgementRangeField = value;
}
/// <remarks/>
[System.Xml.Serialization.XmlElement(Namespace = "http://schemas.microsoft.com/ws/2006/05/rm")]
public byte BufferRemaining
{
get => this.bufferRemainingField;
set => this.bufferRemainingField = value;
}
}
/// <remarks/>
[Serializable()]
[System.ComponentModel.DesignerCategory("code")]
[System.Xml.Serialization.XmlType(AnonymousType = true, Namespace = "http://schemas.xmlsoap.org/ws/2005/02/rm")]
public partial class SequenceAcknowledgementAcknowledgementRange
{
private byte lowerField;
private byte upperField;
/// <remarks/>
[System.Xml.Serialization.XmlAttribute()]
public byte Lower
{
get => this.lowerField;
set => this.lowerField = value;
}
/// <remarks/>
[System.Xml.Serialization.XmlAttribute()]
public byte Upper
{
get => this.upperField;
set => this.upperField = value;
}
}
/// <remarks/>
[Serializable()]
[System.ComponentModel.DesignerCategory("code")]
[System.Xml.Serialization.XmlType(AnonymousType = true, Namespace = "http://www.w3.org/2005/08/addressing")]
[System.Xml.Serialization.XmlRoot(Namespace = "http://www.w3.org/2005/08/addressing", IsNullable = false)]
public partial class Action
{
private byte mustUnderstandField;
private string? valueField;
/// <remarks/>
[System.Xml.Serialization.XmlAttribute(Form = System.Xml.Schema.XmlSchemaForm.Qualified, Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public byte mustUnderstand
{
get => this.mustUnderstandField;
set => this.mustUnderstandField = value;
}
/// <remarks/>
[System.Xml.Serialization.XmlText()]
public string Value
{
get => this.valueField;
set => this.valueField = value;
}
}
/// <remarks/>
[Serializable()]
[System.ComponentModel.DesignerCategory("code")]
[System.Xml.Serialization.XmlType(AnonymousType = true, Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public partial class EnvelopeBody
{
private CreateSequenceResponse? createSequenceResponseField;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Namespace = "http://schemas.xmlsoap.org/ws/2005/02/rm")]
public CreateSequenceResponse CreateSequenceResponse
{
get => this.createSequenceResponseField;
set => this.createSequenceResponseField = value;
}
}
/// <remarks/>
[Serializable()]
[System.ComponentModel.DesignerCategory("code")]
[System.Xml.Serialization.XmlType(AnonymousType = true, Namespace = "http://schemas.xmlsoap.org/ws/2005/02/rm")]
[System.Xml.Serialization.XmlRoot(Namespace = "http://schemas.xmlsoap.org/ws/2005/02/rm", IsNullable = false)]
public partial class CreateSequenceResponse
{
private string? identifierField;
private CreateSequenceResponseAccept? acceptField;
/// <remarks/>
public string Identifier
{
get => this.identifierField;
set => this.identifierField = value;
}
/// <remarks/>
public CreateSequenceResponseAccept Accept
{
get => this.acceptField;
set => this.acceptField = value;
}
}
/// <remarks/>
[Serializable()]
[System.ComponentModel.DesignerCategory("code")]
[System.Xml.Serialization.XmlType(AnonymousType = true, Namespace = "http://schemas.xmlsoap.org/ws/2005/02/rm")]
public partial class CreateSequenceResponseAccept
{
private CreateSequenceResponseAcceptAcksTo? acksToField;
/// <remarks/>
public CreateSequenceResponseAcceptAcksTo AcksTo
{
get => this.acksToField;
set => this.acksToField = value;
}
}
/// <remarks/>
[Serializable()]
[System.ComponentModel.DesignerCategory("code")]
[System.Xml.Serialization.XmlType(AnonymousType = true, Namespace = "http://schemas.xmlsoap.org/ws/2005/02/rm")]
public partial class CreateSequenceResponseAcceptAcksTo
{
private string? addressField;
/// <remarks/>
[System.Xml.Serialization.XmlElement(Namespace = "http://www.w3.org/2005/08/addressing")]
public string Address
{
get => this.addressField;
set => this.addressField = value;
}
}

View File

@ -13,11 +13,18 @@ internal static partial class Helper20250519 {
private record RelativePath(string LeftDirectory,
string? RightDirectory,
Record[] Records);
Record[] Records) {
public override string ToString() {
string result = JsonSerializer.Serialize(this, Helper20250519RelativePath.Default.RelativePath);
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(RelativePath))]
private partial class RelativePathSourceGenerationContext : JsonSerializerContext {
private partial class Helper20250519RelativePath : JsonSerializerContext {
}
private record Review(Segment[]? AreEqual,
@ -26,11 +33,18 @@ internal static partial class Helper20250519 {
Segment[]? NotEqualBut,
Record[]? Records,
Segment[]? RightSideIsNewer,
Segment[]? RightSideOnly);
Segment[]? RightSideOnly) {
public override string ToString() {
string result = JsonSerializer.Serialize(this, Helper20250519Review.Default.Review);
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Review))]
private partial class ReviewSourceGenerationContext : JsonSerializerContext {
private partial class Helper20250519Review : JsonSerializerContext {
}
private record Record(string RelativePath,
@ -49,6 +63,38 @@ internal static partial class Helper20250519 {
long Ticks,
string UrlEncodedFile);
private record Input(string RightDirectory,
string LeftDirectory,
string IncludePatternsFile,
string ExcludePatternsFile,
string[] BaseAddresses,
string Page,
string[] Segments) {
private static string GetDirectory(List<string> args) =>
Path.GetFullPath(args[0].Split('~')[0]);
internal static Input Get(List<string> args) =>
new(RightDirectory: GetDirectory(args),
LeftDirectory: Path.GetFullPath(args[2].Split('~')[0]),
IncludePatternsFile: Path.Combine(GetDirectory(args), ".vscode", args[3]),
ExcludePatternsFile: Path.Combine(GetDirectory(args), ".vscode", args[4]),
BaseAddresses: args.Count < 5 ? [] : args[5].Split('~'),
Page: args[6],
Segments: args[9].Split('~'));
public override string ToString() {
string result = JsonSerializer.Serialize(this, Helper20250519Input.Default.Input);
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Input))]
private partial class Helper20250519Input : JsonSerializerContext {
}
private record Logic(string Comment,
char GreaterThan,
bool? LeftSideIsNewer,
@ -85,53 +131,53 @@ internal static partial class Helper20250519 {
const int leftSideIsNewerIndex = 1;
const int rightSideIsNewerIndex = 3;
string comment = segments[commentIndex];
if (string.IsNullOrEmpty(segments[leftSideOnlyIndex]))
if (string.IsNullOrEmpty(segments[leftSideOnlyIndex])) {
leftSideOnly = null;
else if (segments[leftSideOnlyIndex][0] == plus)
} else if (segments[leftSideOnlyIndex][0] == plus) {
leftSideOnly = true;
else if (segments[leftSideOnlyIndex][0] == minus)
} else if (segments[leftSideOnlyIndex][0] == minus) {
leftSideOnly = false;
else {
} else {
check = false;
leftSideOnly = null;
}
if (string.IsNullOrEmpty(segments[leftSideIsNewerIndex]))
if (string.IsNullOrEmpty(segments[leftSideIsNewerIndex])) {
leftSideIsNewer = null;
else if (segments[leftSideIsNewerIndex][0] == greaterThan)
} else if (segments[leftSideIsNewerIndex][0] == greaterThan) {
leftSideIsNewer = true;
else if (segments[leftSideIsNewerIndex][0] == lessThan)
} else if (segments[leftSideIsNewerIndex][0] == lessThan) {
leftSideIsNewer = false;
else {
} else {
check = false;
leftSideIsNewer = null;
}
if (string.IsNullOrEmpty(segments[notEqualButIndex]))
if (string.IsNullOrEmpty(segments[notEqualButIndex])) {
notEqualBut = null;
else if (segments[notEqualButIndex][0] == greaterThan)
} else if (segments[notEqualButIndex][0] == greaterThan) {
notEqualBut = true;
else if (segments[notEqualButIndex][0] == lessThan)
} else if (segments[notEqualButIndex][0] == lessThan) {
notEqualBut = false;
else {
} else {
check = false;
notEqualBut = null;
}
if (string.IsNullOrEmpty(segments[rightSideIsNewerIndex]))
if (string.IsNullOrEmpty(segments[rightSideIsNewerIndex])) {
rightSideIsNewer = null;
else if (segments[rightSideIsNewerIndex][0] == greaterThan)
} else if (segments[rightSideIsNewerIndex][0] == greaterThan) {
rightSideIsNewer = true;
else if (segments[rightSideIsNewerIndex][0] == lessThan)
} else if (segments[rightSideIsNewerIndex][0] == lessThan) {
rightSideIsNewer = false;
else {
} else {
check = false;
rightSideIsNewer = null;
}
if (string.IsNullOrEmpty(segments[rightSideOnlyIndex]))
if (string.IsNullOrEmpty(segments[rightSideOnlyIndex])) {
rightSideOnly = null;
else if (segments[rightSideOnlyIndex][0] == plus)
} else if (segments[rightSideOnlyIndex][0] == plus) {
rightSideOnly = true;
else if (segments[rightSideOnlyIndex][0] == minus)
} else if (segments[rightSideOnlyIndex][0] == minus) {
rightSideOnly = false;
else {
} else {
check = false;
rightSideOnly = null;
}
@ -154,27 +200,46 @@ internal static partial class Helper20250519 {
return result;
}
public override string ToString() {
string result = JsonSerializer.Serialize(this, Helper20250519Logic.Default.Logic);
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Logic))]
private partial class Helper20250519Logic : JsonSerializerContext {
}
internal static void LiveSync(ILogger<Worker> logger, List<string> args) {
string[] segments = args[9].Split('~');
Logic? logic = segments.Length != 6 ? null : Logic.Get(segments);
string[] baseAddresses = args.Count < 5 ? [] : args[5].Split('~');
if (logic is null || baseAddresses.Length == 0)
logger.LogInformation("Invalid input!");
else {
string rightDirectory = Path.GetFullPath(args[0].Split('~')[0]);
string excludePatternsFile = Path.Combine(rightDirectory, args[4]);
string includePatternsFile = Path.Combine(rightDirectory, args[3]);
Matcher matcher = GetMatcher(excludePatternsFile, includePatternsFile);
ReadOnlyCollection<Record> records = GetRecords(rightDirectory, matcher);
if (records.Count == 0)
logger.LogInformation(args[0]);
logger.LogInformation(args[1]);
logger.LogInformation(args[2]);
if (args[2].EndsWith("input.json") && !File.Exists(args[2])) {
File.WriteAllText(args[2], "{}");
}
string? json = !args[2].EndsWith("input.json") ? null : File.ReadAllText(args[2]);
Input input = string.IsNullOrEmpty(json)
? Input.Get(args)
: JsonSerializer.Deserialize(json, Helper20250519Input.Default.Input)
?? throw new Exception();
Logic? logic = input.Segments.Length != 6 ? null : Logic.Get(input.Segments);
if (logic is null || input.BaseAddresses.Length == 0) {
logger.LogInformation($"Invalid input!{Environment.NewLine}{input}");
} else {
Matcher matcher = GetMatcher(input.ExcludePatternsFile, input.IncludePatternsFile);
ReadOnlyCollection<Record> records = GetRecords(input.RightDirectory, matcher);
if (records.Count == 0) {
logger.LogInformation("No source records");
else {
string page = args[6];
string leftDirectory = Path.GetFullPath(args[2].Split('~')[0]);
RelativePath relativePath = new(LeftDirectory: leftDirectory, RightDirectory: rightDirectory, Records: records.ToArray());
LiveSync180(logger, logic, baseAddresses, page, relativePath);
} else {
RelativePath relativePath = new(LeftDirectory: input.LeftDirectory, RightDirectory: input.RightDirectory, Records: records.ToArray());
json = JsonSerializer.Serialize(relativePath, Helper20250519RelativePath.Default.RelativePath);
if (string.IsNullOrEmpty(json)) {
LiveSync180(logger, logic, input.BaseAddresses, input.Page, relativePath);
} else {
File.WriteAllText(Path.Combine(input.RightDirectory, ".vscode", $"{nameof(RelativePath)}.json"), json);
}
}
}
}
@ -197,11 +262,13 @@ internal static partial class Helper20250519 {
ReadOnlyCollection<ReadOnlyCollection<string>> collection = Helpers.HelperDirectory.GetFilesCollection(directory, "*", "*");
foreach (ReadOnlyCollection<string> c in collection) {
foreach (string f in c) {
if (!matcher.Match(directory, f).HasMatches)
if (!matcher.Match(directory, f).HasMatches) {
continue;
}
fileInfo = new(f);
if (fileInfo.Length == 0)
if (fileInfo.Length == 0) {
continue;
}
relativePath = Path.GetRelativePath(directory, fileInfo.FullName);
record = new(RelativePath: relativePath,
Size: fileInfo.Length,
@ -216,13 +283,14 @@ internal static partial class Helper20250519 {
Review? review;
Task<string> response;
Task<HttpResponseMessage> httpResponseMessage;
StringContent stringContent = new(JsonSerializer.Serialize(relativePath, RelativePathSourceGenerationContext.Default.RelativePath), Encoding.UTF8, "application/json");
string json = JsonSerializer.Serialize(relativePath, Helper20250519RelativePath.Default.RelativePath);
foreach (string baseAddress in baseAddresses) {
if (!baseAddress.StartsWith("http:")) {
logger.LogInformation("Not supported URL <{url}>", baseAddress);
} else {
HttpClient httpClient = new();
httpClient.BaseAddress = new(baseAddress);
StringContent stringContent = new(json, Encoding.UTF8, "application/json");
httpResponseMessage = httpClient.PostAsync(page, stringContent);
httpResponseMessage.Wait();
if (!httpResponseMessage.Result.IsSuccessStatusCode) {
@ -230,7 +298,7 @@ internal static partial class Helper20250519 {
} else {
response = httpResponseMessage.Result.Content.ReadAsStringAsync();
response.Wait();
review = JsonSerializer.Deserialize(response.Result, ReviewSourceGenerationContext.Default.Review);
review = JsonSerializer.Deserialize(response.Result, Helper20250519Review.Default.Review);
if (review is null) {
logger.LogInformation("Failed to download: <{uniformResourceLocator}>;", httpClient.BaseAddress);
continue;
@ -242,26 +310,36 @@ internal static partial class Helper20250519 {
}
private static void LiveSync(ILogger<Worker> logger, Logic l, string page, RelativePath relativePath, HttpClient httpClient, Review review) {
if (review.NotEqualBut.Length > 0 && l is not null && l.NotEqualBut is not null && l.Raw[l.NotEqualButIndex][0] == l.Minus && !l.NotEqualBut.Value)
if (review.NotEqualBut?.Length > 0 && l is not null && l.NotEqualBut is not null && l.Raw[l.NotEqualButIndex][0] == l.Minus && !l.NotEqualBut.Value) {
logger.LogDebug("Doing nothing with {name}", nameof(Logic.NotEqualBut));
if (review.LeftSideOnly.Length > 0 && l is not null && l.LeftSideOnly is not null && l.Raw[l.LeftSideOnlyIndex][0] == l.Minus && !l.LeftSideOnly.Value)
}
if (review.LeftSideOnly?.Length > 0 && l is not null && l.LeftSideOnly is not null && l.Raw[l.LeftSideOnlyIndex][0] == l.Minus && !l.LeftSideOnly.Value) {
LiveSync(logger, page, relativePath, httpClient, relativePath.LeftDirectory, (from x in review.LeftSideOnly select x.Left).ToArray().AsReadOnly(), HttpMethod.Delete, delete: false);
if (review.LeftSideIsNewer.Length > 0 && l is not null && l.LeftSideIsNewer is not null && l.Raw[l.LeftSideIsNewerIndex][0] == l.LessThan && !l.LeftSideIsNewer.Value)
}
if (review.LeftSideIsNewer?.Length > 0 && l is not null && l.LeftSideIsNewer is not null && l.Raw[l.LeftSideIsNewerIndex][0] == l.LessThan && !l.LeftSideIsNewer.Value) {
throw new Exception(); // LiveSync(logger, page, relativePath, httpClient, relativePath.LeftDirectory, (from x in review.LeftSideIsNewer select x.Left).ToArray().AsReadOnly(), HttpMethod.Patch, delete: true);
if (review.RightSideIsNewer.Length > 0 && l is not null && l.RightSideIsNewer is not null && l.Raw[l.RightSideIsNewerIndex][0] == l.LessThan && !l.RightSideIsNewer.Value)
}
if (review.RightSideIsNewer?.Length > 0 && l is not null && l.RightSideIsNewer is not null && l.Raw[l.RightSideIsNewerIndex][0] == l.LessThan && !l.RightSideIsNewer.Value) {
throw new Exception(); // LiveSync(logger, page, relativePath, httpClient, relativePath.RightDirectory, (from x in review.RightSideIsNewer select x.Right).ToArray().AsReadOnly(), HttpMethod.Patch, delete: true);
if (review.RightSideOnly.Length > 0 && l is not null && l.RightSideOnly is not null && l.Raw[l.RightSideOnlyIndex][0] == l.Plus && l.RightSideOnly.Value)
}
if (review.RightSideOnly?.Length > 0 && l is not null && l.RightSideOnly is not null && l.Raw[l.RightSideOnlyIndex][0] == l.Plus && l.RightSideOnly.Value) {
throw new Exception(); // LiveSync(logger, page, relativePath, httpClient, relativePath.RightDirectory, (from x in review.RightSideOnly select x.Right).ToArray().AsReadOnly(), HttpMethod.Put, delete: false);
if (review.RightSideOnly.Length > 0 && l is not null && l.RightSideOnly is not null && l.Raw[l.RightSideOnlyIndex][0] == l.Minus && !l.RightSideOnly.Value)
}
if (review.RightSideOnly?.Length > 0 && l is not null && l.RightSideOnly is not null && l.Raw[l.RightSideOnlyIndex][0] == l.Minus && !l.RightSideOnly.Value) {
LiveSync(logger, page, relativePath, httpClient, relativePath.RightDirectory, (from x in review.RightSideOnly select x.Right).ToArray().AsReadOnly(), httpMethod: null, delete: true);
if (review.LeftSideOnly.Length > 0 && l is not null && l.LeftSideOnly is not null && l.Raw[l.LeftSideOnlyIndex][0] == l.Plus && l.LeftSideOnly.Value)
}
if (review.LeftSideOnly?.Length > 0 && l is not null && l.LeftSideOnly is not null && l.Raw[l.LeftSideOnlyIndex][0] == l.Plus && l.LeftSideOnly.Value) {
LiveSync(logger, page, relativePath, httpClient, relativePath.LeftDirectory, (from x in review.LeftSideOnly select x.Left).ToArray().AsReadOnly(), HttpMethod.Get, delete: false);
if (review.LeftSideIsNewer.Length > 0 && l is not null && l.LeftSideIsNewer is not null && l.Raw[l.LeftSideIsNewerIndex][0] == l.GreaterThan && l.LeftSideIsNewer.Value)
}
if (review.LeftSideIsNewer?.Length > 0 && l is not null && l.LeftSideIsNewer is not null && l.Raw[l.LeftSideIsNewerIndex][0] == l.GreaterThan && l.LeftSideIsNewer.Value) {
LiveSync(logger, page, relativePath, httpClient, relativePath.LeftDirectory, (from x in review.LeftSideIsNewer select x.Left).ToArray().AsReadOnly(), HttpMethod.Get, delete: true);
if (review.NotEqualBut.Length > 0 && l is not null && l.NotEqualBut is not null && l.Raw[l.NotEqualButIndex][0] == l.Plus && l.NotEqualBut.Value)
}
if (review.NotEqualBut?.Length > 0 && l is not null && l.NotEqualBut is not null && l.Raw[l.NotEqualButIndex][0] == l.Plus && l.NotEqualBut.Value) {
LiveSync(logger, page, relativePath, httpClient, relativePath.LeftDirectory, (from x in review.NotEqualBut select x.Left).ToArray().AsReadOnly(), HttpMethod.Get, delete: true);
if (review.RightSideIsNewer.Length > 0 && l is not null && l.RightSideIsNewer is not null && l.Raw[l.RightSideIsNewerIndex][0] == l.GreaterThan && l.RightSideIsNewer.Value)
}
if (review.RightSideIsNewer?.Length > 0 && l is not null && l.RightSideIsNewer is not null && l.Raw[l.RightSideIsNewerIndex][0] == l.GreaterThan && l.RightSideIsNewer.Value) {
LiveSync(logger, page, relativePath, httpClient, relativePath.RightDirectory, (from x in review.RightSideIsNewer select x.Right).ToArray().AsReadOnly(), HttpMethod.Get, delete: true);
}
}
private static void LiveSync(ILogger<Worker> logger, string page, RelativePath relativePath, HttpClient httpClient, string directory, ReadOnlyCollection<Record> records, HttpMethod? httpMethod, bool delete) {
@ -308,8 +386,9 @@ internal static partial class Helper20250519 {
progressBar.Tick();
#endif
record = records[i];
if (record is null)
if (record is null) {
continue;
}
size = GetSizeWithSuffix(record.Size);
try {
File.Delete(Path.Combine(directory, record.RelativePath));
@ -359,9 +438,9 @@ internal static partial class Helper20250519 {
throw new NotImplementedException();
httpResponseMessage = httpClient.SendAsync(httpRequestMessage);
httpResponseMessage.Wait(-1);
if (!httpResponseMessage.Result.IsSuccessStatusCode)
if (!httpResponseMessage.Result.IsSuccessStatusCode) {
logger.LogInformation("Failed to {httpMethod}: <{display}> - {size};", httpMethod, verb.Display, size);
else {
} else {
try {
if (httpMethod != HttpMethod.Get) {
duration = GetDurationWithSuffix(ticks);
@ -401,12 +480,15 @@ internal static partial class Helper20250519 {
checkFile = Path.Combine(directory, record.RelativePath);
checkFileName = Path.GetFileName(checkFile);
checkDirectory = Path.GetDirectoryName(checkFile);
if (string.IsNullOrEmpty(checkDirectory))
if (string.IsNullOrEmpty(checkDirectory)) {
continue;
if (!Directory.Exists(checkDirectory))
}
if (!Directory.Exists(checkDirectory)) {
_ = Directory.CreateDirectory(checkDirectory);
if (File.Exists(checkFile) && new FileInfo(checkFile).Length == 0)
}
if (File.Exists(checkFile) && new FileInfo(checkFile).Length == 0) {
File.Delete(checkFile);
}
verb = new(Directory: checkDirectory,
Display: $"{checkFileName}{Environment.NewLine}{checkDirectory}",
File: checkFile,
@ -419,26 +501,30 @@ internal static partial class Helper20250519 {
}
Verb[] sorted = (from l in collection orderby l.Size select l).ToArray();
int stop = sorted.Length < 100 ? sorted.Length : 100;
for (int i = 0; i < stop; i++)
for (int i = 0; i < stop; i++) {
results.Add(sorted[i]);
for (int i = sorted.Length - 1; i > stop - 1; i--)
}
for (int i = sorted.Length - 1; i > stop - 1; i--) {
results.Add(sorted[i]);
if (collection.Count != results.Count)
}
if (collection.Count != results.Count) {
throw new Exception();
}
return results.AsReadOnly();
}
private static string GetDurationWithSuffix(long ticks) {
string result;
TimeSpan timeSpan = new(DateTime.Now.Ticks - ticks);
if (timeSpan.TotalMilliseconds < 1000)
if (timeSpan.TotalMilliseconds < 1000) {
result = $"{timeSpan.Milliseconds} ms";
else if (timeSpan.TotalMilliseconds < 60000)
} else if (timeSpan.TotalMilliseconds < 60000) {
result = $"{Math.Floor(timeSpan.TotalSeconds)} s";
else if (timeSpan.TotalMilliseconds < 3600000)
} else if (timeSpan.TotalMilliseconds < 3600000) {
result = $"{Math.Floor(timeSpan.TotalMinutes)} m";
else
} else {
result = $"{Math.Floor(timeSpan.TotalHours)} h";
}
return result;
}

View File

@ -1,26 +1,81 @@
using System.Collections.ObjectModel;
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using Microsoft.Extensions.Logging;
namespace File_Folder_Helper.ADO2025.PI6;
internal static partial class Helper20250521 {
[GeneratedRegex(@"[~\-,.0-9]")]
private static partial Regex Number();
[GeneratedRegex(@"[^\u0020-\u007E]")]
private static partial Regex ASCII();
private record Record(string Directory, string FileNameWithoutExtension);
private record LineCheck(string[] Segments, DateTime TransactionDate, DateTime EffectiveDate) {
internal static LineCheck Get(int dateLineSegmentCount, string datePattern, string line) {
LineCheck result;
string[] segments = line.Split(' ');
if (segments.Length >= dateLineSegmentCount
&& segments[0].Length == datePattern.Length
&& segments[1].Length == datePattern.Length
&& DateTime.TryParseExact(segments[0], datePattern, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime transactionDate)
&& DateTime.TryParseExact(segments[1], datePattern, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime effectiveDate)) {
result = new(Segments: segments, TransactionDate: transactionDate, EffectiveDate: effectiveDate);
} else {
result = new(Segments: segments, TransactionDate: DateTime.MinValue, EffectiveDate: DateTime.MinValue);
}
return result;
}
}
private record RecordB(int I,
DateTime TransactionDate,
DateTime EffectiveDate,
string Description,
decimal WithdrawalOrDeposit,
decimal Balance);
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(RecordB[]))]
private partial class Helper20250521RecordB : JsonSerializerContext {
}
internal static void MatchDirectory(ILogger<Worker> logger, List<string> args) {
Record record;
string[] files;
string checkFile;
string datePattern = args[5];
string searchPattern = args[2];
string fileNameWithoutExtension;
string searchPatternB = args[3];
Dictionary<string, string> keyValuePairs = [];
string columns = args[6].Replace('~', ',');
int dateLineSegmentCount = int.Parse(args[4]);
string sourceDirectory = Path.GetFullPath(args[0].Split('~')[0]);
files = Directory.GetFiles(sourceDirectory, searchPattern, SearchOption.AllDirectories);
ReadOnlyDictionary<string, string> keyValuePairs = GetKeyValuePairs(searchPattern, sourceDirectory);
MoveMatchDirectory(searchPatternB, keyValuePairs, sourceDirectory);
ReadOnlyCollection<RecordB> records = GetRecords(searchPatternB, sourceDirectory, dateLineSegmentCount, datePattern, columns);
WriteRecords(sourceDirectory, records);
}
private static ReadOnlyDictionary<string, string> GetKeyValuePairs(string searchPattern, string sourceDirectory) {
Dictionary<string, string> results = [];
string[] files = Directory.GetFiles(sourceDirectory, searchPattern, SearchOption.AllDirectories);
foreach (string file in files) {
keyValuePairs.Add(Path.GetFileNameWithoutExtension(file), Path.GetDirectoryName(file));
results.Add(Path.GetFileNameWithoutExtension(file), Path.GetDirectoryName(file));
}
files = Directory.GetFiles(sourceDirectory, searchPatternB, SearchOption.AllDirectories);
return results.AsReadOnly();
}
private static void MoveMatchDirectory(string searchPatternB, ReadOnlyDictionary<string, string> keyValuePairs, string sourceDirectory) {
string checkFile;
string fileNameWithoutExtension;
string[] files = Directory.GetFiles(sourceDirectory, searchPatternB, SearchOption.AllDirectories);
foreach (string file in files) {
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file);
if (!keyValuePairs.TryGetValue(fileNameWithoutExtension, out string? match))
@ -32,4 +87,98 @@ internal static partial class Helper20250521 {
}
}
private static ReadOnlyCollection<RecordB> GetRecords(string searchPatternB, string sourceDirectory, int dateLineSegmentCount, string datePattern, string columns) {
List<RecordB> results = [];
string line;
string[] lines;
RecordB? record;
LineCheck lineCheck;
string[] files = Directory.GetFiles(sourceDirectory, searchPatternB, SearchOption.AllDirectories);
foreach (string file in files) {
lines = File.ReadAllLines(file);
for (int i = 0; i < lines.Length; i++) {
line = lines[i];
if (string.IsNullOrEmpty(line)) {
continue;
}
lineCheck = LineCheck.Get(dateLineSegmentCount, datePattern, line);
if (lineCheck.EffectiveDate == DateTime.MinValue || lineCheck.TransactionDate == DateTime.MinValue) {
continue;
} else {
record = GetRecord(dateLineSegmentCount, datePattern, lines, i, lineCheck.Segments, lineCheck.TransactionDate, lineCheck.EffectiveDate);
if (record is not null) {
i = record.I;
results.Add(record);
}
}
}
}
return results.AsReadOnly();
}
private static RecordB? GetRecord(int dateLineSegmentCount, string datePattern, string[] lines, int i, string[] segments, DateTime transactionDate, DateTime effectiveDate) {
RecordB? result = null;
string line;
RecordB record;
LineCheck lineCheck;
List<string> collection = [];
for (int j = i + 1; j < lines.Length; j++) {
line = lines[j];
if (string.IsNullOrEmpty(line)) {
continue;
}
lineCheck = LineCheck.Get(dateLineSegmentCount, datePattern, line);
if (lineCheck.EffectiveDate == DateTime.MinValue || lineCheck.TransactionDate == DateTime.MinValue) {
collection.Add(line);
} else {
if (lineCheck.Segments.Length > dateLineSegmentCount) {
collection.Insert(0, string.Join(' ', lineCheck.Segments.Skip(2)));
}
result = GetRecord(transactionDate, effectiveDate, collection.AsReadOnly(), j - 1);
break;
}
}
if (result is null && collection.Count > 0) {
result = GetRecord(transactionDate, effectiveDate, collection.AsReadOnly(), lines.Length - 1);
}
return result;
}
private static RecordB GetRecord(DateTime transactionDate, DateTime effectiveDate, ReadOnlyCollection<string> collection, int i) {
RecordB? result;
List<string> verified = [];
foreach (string check in collection) {
if (Number().Replace(check, string.Empty).Length != 0) {
verified.Clear();
} else {
verified.Add(check);
}
if (verified.Count == 2) {
break;
}
}
if (verified.Count != 2) {
result = null;
} else {
decimal balance = decimal.Parse(verified[^1]);
decimal withdrawalOrDeposit = decimal.Parse(verified[^2]);
string description = ASCII().Replace(string.Join(' ', collection.SkipLast(2)), string.Empty);
result = new(I: i,
TransactionDate: transactionDate,
EffectiveDate: effectiveDate,
Description: description,
WithdrawalOrDeposit: withdrawalOrDeposit,
Balance: balance);
}
return result;
}
private static void WriteRecords(string sourceDirectory, ReadOnlyCollection<RecordB> records) {
string json = JsonSerializer.Serialize(records.ToArray(), Helper20250521RecordB.Default.RecordBArray);
string sourceDirectoryVsCode = Path.Combine(sourceDirectory, ".vscode");
if (!Directory.Exists(sourceDirectoryVsCode))
_ = Directory.CreateDirectory(sourceDirectoryVsCode);
File.WriteAllText(Path.Combine(sourceDirectoryVsCode, $"{DateTime.Now.Ticks}.json"), json);
}
}

View File

@ -0,0 +1,394 @@
using System.Collections.ObjectModel;
using System.Globalization;
using System.Net;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using IFX.Shared.PasteSpecialXml.EAF.XML.API.Envelope;
using Microsoft.Extensions.Logging;
namespace File_Folder_Helper.ADO2025.PI6;
internal static partial class Helper20250601 {
private static readonly bool _IsEnvironment_Development = false;
private record Record(string Text, string Host, int Port, string[] Segments, bool StateContainsDisabled);
private record Status(string CellInstanceName,
string CommunicationState,
string CurrentActiveVersion,
string CurrentHost,
string ErrorDescription,
string Host,
string IsReadyForRestart,
string NPort,
int Port,
string StartTime,
string Startable,
string State,
string StopTime,
string Text);
internal static void EquipmentAutomationFrameworkStatus(ILogger<Worker> logger, List<string> args) {
Status status;
Record? record;
List<string[]> messages;
logger.LogInformation(args[0]);
logger.LogInformation(args[1]);
logger.LogInformation(args[2]);
string[] cellInstanceNames = args[2].Split('~');
Dictionary<string, Record> records;
if (_IsEnvironment_Development) {
records = GetEquipmentAutomationFrameworkCellInstanceStatus(development: true, staging: false, production: false);
} else {
records = GetEquipmentAutomationFrameworkCellInstanceStatus(development: false, staging: true, production: true);
}
foreach (string cellInstanceName in cellInstanceNames) {
if (!records.TryGetValue(cellInstanceName, out record)) {
logger.LogWarning("{cellInstance} not found!", cellInstanceName);
continue;
}
status = EquipmentAutomationFrameworkCellInstanceStatus(cellInstanceName, record);
logger.LogInformation("{host}) {cellInstanceName} => {status}", record.Host, cellInstanceName, status.ToString());
}
}
private static Dictionary<string, Record> GetEquipmentAutomationFrameworkCellInstanceStatus(bool development, bool staging, bool production) {
Dictionary<string, Record> results = [];
string key;
string host;
string text;
string state;
string response;
bool stop = false;
string[] segments;
string[] cellNames;
byte[] responseBytes;
string responseAfter;
#pragma warning disable SYSLIB0014
WebClient webClient = new();
#pragma warning restore SYSLIB0014
string disabled = "Disabled";
UnicodeCategory unicodeCategory;
StringBuilder stringBuilder = new();
EquipmentAutomationFrameworkCellInstanceParseCheck();
Dictionary<char, char> unicodeReplaces = GetUnicodeReplaces();
List<UnicodeCategory> unicodeCategories = GetUnicodeCategory();
ReadOnlyCollection<string> urls = GetUrls(development, staging, production);
// Dictionary<UnicodeCategory, List<char>> unicodeCategoriesList = new Dictionary<UnicodeCategory, List<char>>();
byte[] bodyBytes = [86, 2, 11, 1, 115, 4, 11, 1, 97, 6, 86, 8, 68, 10, 30, 0, 130, 153, 48, 104, 116, 116, 112, 58, 47, 47, 116, 101, 109, 112, 117, 114, 105, 46, 111, 114, 103, 47, 73, 83, 116, 97, 116, 117, 115, 81, 117, 101, 114, 121, 47, 71, 101, 116, 70, 97, 99, 116, 111, 114, 121, 83, 116, 97, 116, 117, 115, 68, 26, 173, 181, 241, 2, 149, 65, 209, 208, 66, 143, 234, 233, 157, 246, 118, 78, 238, 68, 44, 68, 42, 171, 20, 1, 68, 12, 30, 0, 130, 153, 49, 104, 116, 116, 112, 58, 47, 47, 101, 97, 102, 45, 112, 114, 111, 100, 46, 109, 101, 115, 46, 105, 110, 102, 105, 110, 101, 111, 110, 46, 99, 111, 109, 58, 57, 48, 48, 51, 47, 83, 116, 97, 116, 117, 115, 81, 117, 101, 114, 121, 1, 86, 14, 64, 16, 71, 101, 116, 70, 97, 99, 116, 111, 114, 121, 83, 116, 97, 116, 117, 115, 8, 19, 104, 116, 116, 112, 58, 47, 47, 116, 101, 109, 112, 117, 114, 105, 46, 111, 114, 103, 47, 64, 16, 105, 110, 99, 108, 117, 100, 101, 65, 103, 101, 110, 116, 76, 105, 115, 116, 135, 64, 17, 105, 110, 99, 108, 117, 100, 101, 83, 116, 97, 116, 117, 115, 76, 105, 115, 116, 135, 64, 23, 101, 120, 116, 101, 110, 100, 101, 100, 83, 116, 97, 116, 117, 115, 67, 101, 108, 108, 78, 97, 109, 101, 115, 9, 1, 98, 57, 104, 116, 116, 112, 58, 47, 47, 115, 99, 104, 101, 109, 97, 115, 46, 109, 105, 99, 114, 111, 115, 111, 102, 116, 46, 99, 111, 109, 47, 50, 48, 48, 51, 47, 49, 48, 47, 83, 101, 114, 105, 97, 108, 105, 122, 97, 116, 105, 111, 110, 47, 65, 114, 114, 97, 121, 115, 9, 1, 105, 41, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 119, 51, 46, 111, 114, 103, 47, 50, 48, 48, 49, 47, 88, 77, 76, 83, 99, 104, 101, 109, 97, 45, 105, 110, 115, 116, 97, 110, 99, 101, 95, 6, 115, 116, 114, 105, 110, 103, 153, 20, 66, 73, 79, 82, 65, 68, 53, 95, 70, 105, 108, 101, 65, 114, 99, 104, 105, 118, 101, 114, 1, 1, 1, 1];
foreach (string url in urls) {
if (stop) {
break;
}
segments = url.Split(':');
host = segments[0];
if (segments.Length == 0 || !int.TryParse(segments[1], out int port)) {
port = 80;
}
webClient.Headers.Clear();
webClient.Headers.Add("Accept-Encoding: gzip, deflate");
webClient.Headers.Add("Content-Type: application/soap+msbin1");
responseBytes = webClient.UploadData($"http://{host}:{port}/StatusQuery", bodyBytes);
// File.WriteAllText(@"L:\Tmp\a.txt", BitConverter.ToString(responseBytes));
response = Encoding.UTF8.GetString(responseBytes);
foreach (char c in response) {
unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c);
if (unicodeCategory == UnicodeCategory.Control && unicodeReplaces.ContainsKey(c)) {
_ = stringBuilder.Append(unicodeReplaces[c]);
} else if (unicodeCategories.Contains(unicodeCategory)) {
_ = stringBuilder.Append(c);
}
}
responseAfter = stringBuilder.ToString();
cellNames = responseAfter.Split(new string[] { "CellName" }, StringSplitOptions.None);
foreach (string segment in cellNames) {
if (stop) {
break;
}
key = string.Empty;
state = string.Empty;
segments = segment.Split(new string[] { "WindowsName" }, StringSplitOptions.None);
if (segments.Length != 2) {
continue;
}
text = segments[0];
segments = text.Replace('\r', ' ').Replace('\n', ' ').Split(' ');
for (int i = 0; i < segments.Length - 3; i++) {
if (stop) {
break;
}
if (!string.IsNullOrEmpty(segments[i]) && string.IsNullOrEmpty(key)) {
key = segments[i].Trim();
} else if (segments[i].StartsWith("State")) {
state = segments[i + 1];
break;
}
}
if (key.EndsWith("a")) {
key = key[..^1];
}
if (!results.ContainsKey(key)) {
results.Add(key, new Record(Text: text, Host: host, Port: port, Segments: segments, StateContainsDisabled: state.Contains(disabled)));
} else if (results[key].StateContainsDisabled) {
results[key] = new Record(Text: text, Host: host, Port: port, Segments: segments, StateContainsDisabled: state.Contains(disabled));
}
}
}
return results;
}
private static ReadOnlyCollection<string> GetUrls(bool development, bool staging, bool production) {
List<string> results = [];
if (development) {
results.Add("eaf-dev.mes.infineon.com:9003");
}
if (staging) {
results.Add("eaf-staging.mes.infineon.com:9003");
}
if (production) {
results.Add("eaf-prod.mes.infineon.com:9003");
}
return results.AsReadOnly();
}
private static List<UnicodeCategory> GetUnicodeCategory() {
List<UnicodeCategory> unicodeCategories = [
// UnicodeCategory.Control, // 33 - <20>
UnicodeCategory.UppercaseLetter, // 25 - ABCDEFGHIJKLMNOPQRSTUVWXY
UnicodeCategory.LowercaseLetter, // 25 - abcdefghiklmnopqrstuvwxyz
UnicodeCategory.DecimalDigitNumber, // 10 - 0123456789
UnicodeCategory.OtherPunctuation, // 10 - !"#%&,./:@
UnicodeCategory.ClosePunctuation, // 2 - )]
UnicodeCategory.MathSymbol, // 2 - |؈
UnicodeCategory.OpenPunctuation, // 2 - ([
// UnicodeCategory.OtherSymbol, // 1 - <20>
UnicodeCategory.DashPunctuation, // 1 - -
UnicodeCategory.ConnectorPunctuation, // 1 - _
UnicodeCategory.ModifierSymbol, // 1 - `
UnicodeCategory.NonSpacingMark, // 1 - ̵
UnicodeCategory.SpaceSeparator, // 1 -
UnicodeCategory.CurrencySymbol, // 1 - $
];
return unicodeCategories;
}
private static void EquipmentAutomationFrameworkCellInstanceParseCheck() {
Envelope? envelope;
string xmlStart621 = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequenceResponse</a:Action><a:RelatesTo>urn:uuid:6eb7a538-0b2b-4d04-8f2a-ab50e1e5338a</a:RelatesTo></s:Header><s:Body><CreateSequenceResponse xmlns=\"http://schemas.xmlsoap.org/ws/2005/02/rm\"><Identifier>urn:uuid:31c290af-2312-4b00-a57c-d5e1ab51e02a</Identifier><Accept><AcksTo><a:Address>http://eaf-prod.mes.infineon.com:9003/CellControllerManager</a:Address></AcksTo></Accept></CreateSequenceResponse></s:Body></s:Envelope>";
string xmlStart891 = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:r=\"http://schemas.xmlsoap.org/ws/2005/02/rm\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><r:Sequence s:mustUnderstand=\"1\"><r:Identifier>urn:uuid:f169e50f-5ca8-43cd-a1e9-724840ff5e00</r:Identifier><r:MessageNumber>1</r:MessageNumber></r:Sequence><r:SequenceAcknowledgement><r:Identifier>urn:uuid:31c290af-2312-4b00-a57c-d5e1ab51e02a</r:Identifier><r:AcknowledgementRange Lower=\"1\" Upper=\"1\"/><netrm:BufferRemaining xmlns:netrm=\"http://schemas.microsoft.com/ws/2006/05/rm\">8</netrm:BufferRemaining></r:SequenceAcknowledgement><a:Action s:mustUnderstand=\"1\">http://tempuri.org/ICellControllerManager/StartAllCellInstancesResponse</a:Action><a:RelatesTo>urn:uuid:38977fa4-262a-42fb-8df7-d8d3074820b2</a:RelatesTo></s:Header><s:Body><StartAllCellInstancesResponse xmlns=\"http://tempuri.org/\"/></s:Body></s:Envelope>";
string xmlStart748 = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:r=\"http://schemas.xmlsoap.org/ws/2005/02/rm\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><r:Sequence s:mustUnderstand=\"1\"><r:Identifier>urn:uuid:f169e50f-5ca8-43cd-a1e9-724840ff5e00</r:Identifier><r:MessageNumber>2</r:MessageNumber><r:LastMessage/></r:Sequence><r:SequenceAcknowledgement><r:Identifier>urn:uuid:31c290af-2312-4b00-a57c-d5e1ab51e02a</r:Identifier><r:AcknowledgementRange Lower=\"1\" Upper=\"2\"/><netrm:BufferRemaining xmlns:netrm=\"http://schemas.microsoft.com/ws/2006/05/rm\">8</netrm:BufferRemaining></r:SequenceAcknowledgement><a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/rm/LastMessage</a:Action></s:Header><s:Body/></s:Envelope>";
string xmlStart707 = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:r=\"http://schemas.xmlsoap.org/ws/2005/02/rm\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><r:SequenceAcknowledgement><r:Identifier>urn:uuid:31c290af-2312-4b00-a57c-d5e1ab51e02a</r:Identifier><r:AcknowledgementRange Lower=\"1\" Upper=\"2\"/><netrm:BufferRemaining xmlns:netrm=\"http://schemas.microsoft.com/ws/2006/05/rm\">8</netrm:BufferRemaining></r:SequenceAcknowledgement><a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/rm/TerminateSequence</a:Action></s:Header><s:Body><r:TerminateSequence><r:Identifier>urn:uuid:f169e50f-5ca8-43cd-a1e9-724840ff5e00</r:Identifier></r:TerminateSequence></s:Body></s:Envelope>";
string xmlStop621 = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequenceResponse</a:Action><a:RelatesTo>urn:uuid:97f7aeb4-015f-440b-b0ff-a2a5aa4f4ab9</a:RelatesTo></s:Header><s:Body><CreateSequenceResponse xmlns=\"http://schemas.xmlsoap.org/ws/2005/02/rm\"><Identifier>urn:uuid:e34d16ad-21d5-4a11-a6dc-5b5b58a74f96</Identifier><Accept><AcksTo><a:Address>http://eaf-prod.mes.infineon.com:9003/CellControllerManager</a:Address></AcksTo></Accept></CreateSequenceResponse></s:Body></s:Envelope>";
string xmlStop889 = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:r=\"http://schemas.xmlsoap.org/ws/2005/02/rm\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><r:Sequence s:mustUnderstand=\"1\"><r:Identifier>urn:uuid:c9a4d5b6-435b-49a4-a2f9-d93cd8aecc36</r:Identifier><r:MessageNumber>1</r:MessageNumber></r:Sequence><r:SequenceAcknowledgement><r:Identifier>urn:uuid:e34d16ad-21d5-4a11-a6dc-5b5b58a74f96</r:Identifier><r:AcknowledgementRange Lower=\"1\" Upper=\"1\"/><netrm:BufferRemaining xmlns:netrm=\"http://schemas.microsoft.com/ws/2006/05/rm\">8</netrm:BufferRemaining></r:SequenceAcknowledgement><a:Action s:mustUnderstand=\"1\">http://tempuri.org/ICellControllerManager/StopAllCellInstancesResponse</a:Action><a:RelatesTo>urn:uuid:04b8b0ea-8576-4756-b456-8a817cd10826</a:RelatesTo></s:Header><s:Body><StopAllCellInstancesResponse xmlns=\"http://tempuri.org/\"/></s:Body></s:Envelope>";
string xmlStop748 = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:r=\"http://schemas.xmlsoap.org/ws/2005/02/rm\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><r:Sequence s:mustUnderstand=\"1\"><r:Identifier>urn:uuid:c9a4d5b6-435b-49a4-a2f9-d93cd8aecc36</r:Identifier><r:MessageNumber>2</r:MessageNumber><r:LastMessage/></r:Sequence><r:SequenceAcknowledgement><r:Identifier>urn:uuid:e34d16ad-21d5-4a11-a6dc-5b5b58a74f96</r:Identifier><r:AcknowledgementRange Lower=\"1\" Upper=\"2\"/><netrm:BufferRemaining xmlns:netrm=\"http://schemas.microsoft.com/ws/2006/05/rm\">8</netrm:BufferRemaining></r:SequenceAcknowledgement><a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/rm/LastMessage</a:Action></s:Header><s:Body/></s:Envelope>";
string xmlStop707 = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:r=\"http://schemas.xmlsoap.org/ws/2005/02/rm\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><r:SequenceAcknowledgement><r:Identifier>urn:uuid:e34d16ad-21d5-4a11-a6dc-5b5b58a74f96</r:Identifier><r:AcknowledgementRange Lower=\"1\" Upper=\"2\"/><netrm:BufferRemaining xmlns:netrm=\"http://schemas.microsoft.com/ws/2006/05/rm\">8</netrm:BufferRemaining></r:SequenceAcknowledgement><a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/rm/TerminateSequence</a:Action></s:Header><s:Body><r:TerminateSequence><r:Identifier>urn:uuid:c9a4d5b6-435b-49a4-a2f9-d93cd8aecc36</r:Identifier></r:TerminateSequence></s:Body></s:Envelope>";
string xmlRestart621 = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequenceResponse</a:Action><a:RelatesTo>urn:uuid:e228a621-e7ab-4ebf-97ba-5571cb5f4ad7</a:RelatesTo></s:Header><s:Body><CreateSequenceResponse xmlns=\"http://schemas.xmlsoap.org/ws/2005/02/rm\"><Identifier>urn:uuid:a1650ed7-34dc-4fac-993f-ed2559c453a2</Identifier><Accept><AcksTo><a:Address>http://eaf-prod.mes.infineon.com:9003/CellControllerManager</a:Address></AcksTo></Accept></CreateSequenceResponse></s:Body></s:Envelope>";
string xmlRestart895 = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:r=\"http://schemas.xmlsoap.org/ws/2005/02/rm\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><r:Sequence s:mustUnderstand=\"1\"><r:Identifier>urn:uuid:50c82506-bd4d-4117-b632-640cf84d556e</r:Identifier><r:MessageNumber>1</r:MessageNumber></r:Sequence><r:SequenceAcknowledgement><r:Identifier>urn:uuid:a1650ed7-34dc-4fac-993f-ed2559c453a2</r:Identifier><r:AcknowledgementRange Lower=\"1\" Upper=\"1\"/><netrm:BufferRemaining xmlns:netrm=\"http://schemas.microsoft.com/ws/2006/05/rm\">8</netrm:BufferRemaining></r:SequenceAcknowledgement><a:Action s:mustUnderstand=\"1\">http://tempuri.org/ICellControllerManager/RestartAllCellInstancesResponse</a:Action><a:RelatesTo>urn:uuid:efaeaf12-4aa0-4cd1-8296-05019e47261a</a:RelatesTo></s:Header><s:Body><RestartAllCellInstancesResponse xmlns=\"http://tempuri.org/\"/></s:Body></s:Envelope>";
string xmlRestart748 = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:r=\"http://schemas.xmlsoap.org/ws/2005/02/rm\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><r:Sequence s:mustUnderstand=\"1\"><r:Identifier>urn:uuid:50c82506-bd4d-4117-b632-640cf84d556e</r:Identifier><r:MessageNumber>2</r:MessageNumber><r:LastMessage/></r:Sequence><r:SequenceAcknowledgement><r:Identifier>urn:uuid:a1650ed7-34dc-4fac-993f-ed2559c453a2</r:Identifier><r:AcknowledgementRange Lower=\"1\" Upper=\"2\"/><netrm:BufferRemaining xmlns:netrm=\"http://schemas.microsoft.com/ws/2006/05/rm\">8</netrm:BufferRemaining></r:SequenceAcknowledgement><a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/rm/LastMessage</a:Action></s:Header><s:Body/></s:Envelope>";
string xmlRestart707 = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:r=\"http://schemas.xmlsoap.org/ws/2005/02/rm\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><r:SequenceAcknowledgement><r:Identifier>urn:uuid:a1650ed7-34dc-4fac-993f-ed2559c453a2</r:Identifier><r:AcknowledgementRange Lower=\"1\" Upper=\"2\"/><netrm:BufferRemaining xmlns:netrm=\"http://schemas.microsoft.com/ws/2006/05/rm\">8</netrm:BufferRemaining></r:SequenceAcknowledgement><a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/rm/TerminateSequence</a:Action></s:Header><s:Body><r:TerminateSequence><r:Identifier>urn:uuid:50c82506-bd4d-4117-b632-640cf84d556e</r:Identifier></r:TerminateSequence></s:Body></s:Envelope>";
string[] xmlSets = [xmlStart621, xmlStart891, xmlStart748, xmlStart707, xmlStop621, xmlStop889, xmlStop748, xmlStop707, xmlRestart621, xmlRestart895, xmlRestart748, xmlRestart707];
foreach (string xmlSet in xmlSets) {
envelope = ParseXML<Envelope>(xmlSet, throwExceptions: true);
}
}
private static T? ParseXML<T>(string value, bool throwExceptions) where T : class {
object? result = null;
try {
Stream stream = ToStream(value.Trim());
XmlReader xmlReader = XmlReader.Create(stream, new XmlReaderSettings() { ConformanceLevel = ConformanceLevel.Document });
#pragma warning disable IL2026, IL2090
XmlSerializer xmlSerializer = new(typeof(T), typeof(T).GetNestedTypes());
result = xmlSerializer.Deserialize(xmlReader);
#pragma warning restore IL2026, IL2090
stream.Dispose();
} catch (Exception) {
if (throwExceptions) {
throw;
}
}
return result as T;
}
private static Stream ToStream(string value) {
MemoryStream memoryStream = new();
StreamWriter streamWriter = new(memoryStream);
streamWriter.Write(value);
streamWriter.Flush();
memoryStream.Position = 0;
return memoryStream;
}
private static Dictionary<char, char> GetUnicodeReplaces() {
Dictionary<char, char> results = new() {
{ '\u0000', ' ' },
{ '\u0001', ' ' },
{ '\u0002', ' ' },
{ '\u0003', ' ' },
{ '\u0004', ' ' },
{ '\u0005', ' ' },
{ '\u0006', ' ' },
{ '\u0007', ' ' },
{ '\u0008', ' ' },
{ '\u0009', '\t' },
{ '\u000A', '\r' },
{ '\u000B', '\r' },
{ '\u000C', '\t' },
{ '\u000D', '\r' },
{ '\u000E', ' ' },
{ '\u000F', ' ' },
{ '\u0010', ' ' },
{ '\u0011', ' ' },
{ '\u0012', ' ' },
{ '\u0013', ' ' },
{ '\u0014', ' ' },
{ '\u0015', ' ' },
{ '\u0016', ' ' },
{ '\u0017', ' ' },
{ '\u0018', ' ' },
{ '\u0019', ' ' },
{ '\u001A', ' ' },
{ '\u001B', ' ' },
{ '\u001C', '\r' },
{ '\u001D', '\t' },
{ '\u001E', '\t' },
{ '\u001F', '\t' },
{ '\u007F', ' ' },
// C1
{ '\u0080', '\t' },
{ '\u0081', ' ' },
{ '\u0082', ' ' },
{ '\u0083', ' ' },
{ '\u0084', ' ' },
{ '\u0085', '\r' },
{ '\u0086', ' ' },
{ '\u0087', ' ' },
{ '\u0088', '\t' },
{ '\u0089', '\t' },
{ '\u008A', '\t' },
{ '\u008B', '\r' },
{ '\u008C', ' ' },
{ '\u008D', ' ' },
{ '\u008E', ' ' },
{ '\u008F', ' ' },
{ '\u0090', ' ' },
{ '\u0091', ' ' },
{ '\u0092', ' ' },
{ '\u0093', ' ' },
{ '\u0094', ' ' },
{ '\u0095', ' ' },
{ '\u0096', ' ' },
{ '\u0097', ' ' },
{ '\u0098', ' ' },
{ '\u0099', ' ' },
{ '\u009A', ' ' },
{ '\u009B', ' ' },
{ '\u009C', ' ' },
{ '\u009D', ' ' },
{ '\u009E', ' ' },
{ '\u009F', ' ' }
};
return results;
}
private static Status EquipmentAutomationFrameworkCellInstanceStatus(string cellInstanceName, Record record) {
Status result;
bool stop = false;
string state = string.Empty;
string stopTime = string.Empty;
string startTime = string.Empty;
string startable = string.Empty;
string currentHost = string.Empty;
string errorDescription = string.Empty;
string isReadyForRestart = string.Empty;
string communicationState = string.Empty;
string currentActiveVersion = string.Empty;
for (int i = 0; i < record.Segments.Length - 3; i++) {
if (stop) {
break;
}
if (string.IsNullOrEmpty(state) && record.Segments[i].StartsWith("State")) {
state = record.Segments[i + 1];
} else if (string.IsNullOrEmpty(startable) && record.Segments[i].Contains("Startable")) {
startable = record.Segments[i + 1];
} else if (string.IsNullOrEmpty(stopTime) && record.Segments[i].StartsWith("StopTime")) {
stopTime = record.Segments[i + 1];
} else if (string.IsNullOrEmpty(currentHost) && record.Segments[i].Contains("CurrentHost")) {
currentHost = $"{record.Segments[i]} {record.Segments[i + 1]} {record.Segments[i + 2]}";
} else if (string.IsNullOrEmpty(errorDescription) && record.Segments[i].StartsWith("ErrorDescription")) {
errorDescription = record.Segments[i + 1];
} else if (string.IsNullOrEmpty(communicationState) && record.Segments[i].StartsWith("CommunicationState")) {
communicationState = record.Segments[i + 1];
} else if (string.IsNullOrEmpty(isReadyForRestart) && record.Segments[i].StartsWith("IsReadyForRestart")) {
isReadyForRestart = record.Segments[i + 1];
} else if (string.IsNullOrEmpty(currentActiveVersion) && record.Segments[i].Contains("CurrentActiveVersion")) {
currentActiveVersion = record.Segments[i + 1];
} else if (string.IsNullOrEmpty(startTime) && record.Segments[i].Contains("StartTime")) {
startTime = $"{record.Segments[i + 1]} {record.Segments[i + 2]} {record.Segments[i + 3]}".Split('\t')[0];
}
}
if (errorDescription != "a") {
string[] segments = record.Text.Split(new string[] { "ErrorDescription" }, StringSplitOptions.RemoveEmptyEntries);
if (segments.Length > 1) {
segments = segments[1].Split(new string[] { "Info" }, StringSplitOptions.RemoveEmptyEntries);
errorDescription = segments[0].Trim();
}
}
string nPort;
Dictionary<string, string> nPorts = GetnPorts();
if (!nPorts.ContainsKey(cellInstanceName)) {
nPort = string.Empty;
} else {
nPort = nPorts[cellInstanceName];
}
if (state.EndsWith("a")) {
state = state[0..^1];
}
if (state == "Running" && communicationState == "Not") {
state = "Warning";
}
result = new(Host: record.Host,
Port: record.Port,
Text: record.Text,
NPort: nPort,
State: state,
CellInstanceName: cellInstanceName,
StopTime: stopTime,
StartTime: startTime,
Startable: startable,
CurrentHost: currentHost,
ErrorDescription: errorDescription,
IsReadyForRestart: isReadyForRestart,
CommunicationState: communicationState,
CurrentActiveVersion: currentActiveVersion);
return result;
}
private static Dictionary<string, string> GetnPorts() {
Dictionary<string, string> results = new() {
{ "TENCOR1", "10.95.192.31" },
{ "TENCOR2", "10.95.192.32" },
{ "TENCOR3", "10.95.192.33" },
{ "HGCV1", "10.95.192.34" },
{ "HGCV2", "10.95.154.17" },
{ "HGCV3", "10.95.192.36" },
{ "BIORAD2", "10.95.192.37" },
{ "BIORAD3", "10.95.192.38" },
{ "CDE2", "10.95.192.39" },
{ "CDE3", "10.95.154.19" },
{ "CDE5", "10.95.192.40" },
{ "SPARE-1", "10.95.192.47" },
{ "SPARE-2", "10.95.192.48" },
{ "SPARE-3", "10.95.192.49" },
{ "SPARE-4", "10.95.192.50" },
{ "SPARE-5", "10.95.192.51" },
};
return results;
}
}

View File

@ -0,0 +1,545 @@
using System.Collections.ObjectModel;
using System.Globalization;
using System.Net;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using IFX.Shared.PasteSpecialXml.EAF.XML.API.Envelope;
using Microsoft.Extensions.Logging;
namespace File_Folder_Helper.ADO2025.PI6;
internal static partial class Helper20250602 {
private record Record(string Text, string Host, int Port, string[] Segments, bool StateContainsDisabled);
private record Status(string CellInstanceName,
string CommunicationState,
string CurrentActiveVersion,
string CurrentHost,
string ErrorDescription,
string Host,
string IsReadyForRestart,
string NPort,
int Port,
string StartTime,
string Startable,
string State,
string StopTime,
string Text);
internal static void EquipmentAutomationFrameworkCellInstanceStateImageVerbIf(ILogger<Worker> logger, List<string> args) {
string path;
Status status;
Record? record;
string verbBy = args[2];
logger.LogInformation(args[0]);
logger.LogInformation(args[1]);
logger.LogInformation(args[2]);
logger.LogInformation(args[3]);
string[] cellInstanceNames = args[3].Split('~');
Dictionary<string, Record> records = GetEquipmentAutomationFrameworkCellInstanceStatus(development: false, staging: false, production: true);
foreach (string cellInstanceName in cellInstanceNames) {
if (!records.TryGetValue(cellInstanceName, out record)) {
logger.LogWarning("{cellInstance} not found!", cellInstanceName);
continue;
}
if (records[cellInstanceName].StateContainsDisabled) {
logger.LogWarning("{cellInstance} not found!", cellInstanceName);
}
status = GetEquipmentAutomationFrameworkCellInstanceStateImageVerbIf(logger, verbBy, cellInstanceName, record);
path = $"/images/{cellInstanceName}_{status.State}.jpg";
logger.LogInformation("{host}) {cellInstanceName} => {state} <{path}>", record.Host, cellInstanceName, status.State, path);
}
}
private static Status GetEquipmentAutomationFrameworkCellInstanceStateImageVerbIf(ILogger<Worker> logger, string verbBy, string cellInstanceName, Record record) {
Status result;
Dictionary<string, DateTime> equipmentAutomationFrameworkTriggers = [];
if (!equipmentAutomationFrameworkTriggers.ContainsKey(cellInstanceName)) {
equipmentAutomationFrameworkTriggers.Add(cellInstanceName, DateTime.MinValue);
}
result = EquipmentAutomationFrameworkCellInstanceStatus(cellInstanceName, record);
if (equipmentAutomationFrameworkTriggers[cellInstanceName] < DateTime.Now.AddSeconds(-60)) {
if (result.State == "Offline") {
EquipmentAutomationFrameworkCellInstanceStart(record.Host, record.Port, cellInstanceName, verbBy);
logger.LogInformation("Start invoked for {cellName}", cellInstanceName);
} else if (result.State == "Warning") {
EquipmentAutomationFrameworkCellInstanceRestart(record.Host, record.Port, cellInstanceName, verbBy);
logger.LogInformation("Restart invoked for {cellName}", cellInstanceName);
}
}
return result;
}
private static Dictionary<string, Record> GetEquipmentAutomationFrameworkCellInstanceStatus(bool development, bool staging, bool production) {
Dictionary<string, Record> results = [];
string key;
string host;
string text;
string state;
string response;
bool stop = false;
string[] segments;
string[] cellNames;
byte[] responseBytes;
string responseAfter;
#pragma warning disable SYSLIB0014
WebClient webClient = new();
#pragma warning restore SYSLIB0014
string disabled = "Disabled";
UnicodeCategory unicodeCategory;
StringBuilder stringBuilder = new();
EquipmentAutomationFrameworkCellInstanceParseCheck();
Dictionary<char, char> unicodeReplaces = GetUnicodeReplaces();
List<UnicodeCategory> unicodeCategories = GetUnicodeCategory();
ReadOnlyCollection<string> urls = GetUrls(development, staging, production);
// Dictionary<UnicodeCategory, List<char>> unicodeCategoriesList = new Dictionary<UnicodeCategory, List<char>>();
byte[] bodyBytes = [86, 2, 11, 1, 115, 4, 11, 1, 97, 6, 86, 8, 68, 10, 30, 0, 130, 153, 48, 104, 116, 116, 112, 58, 47, 47, 116, 101, 109, 112, 117, 114, 105, 46, 111, 114, 103, 47, 73, 83, 116, 97, 116, 117, 115, 81, 117, 101, 114, 121, 47, 71, 101, 116, 70, 97, 99, 116, 111, 114, 121, 83, 116, 97, 116, 117, 115, 68, 26, 173, 181, 241, 2, 149, 65, 209, 208, 66, 143, 234, 233, 157, 246, 118, 78, 238, 68, 44, 68, 42, 171, 20, 1, 68, 12, 30, 0, 130, 153, 49, 104, 116, 116, 112, 58, 47, 47, 101, 97, 102, 45, 112, 114, 111, 100, 46, 109, 101, 115, 46, 105, 110, 102, 105, 110, 101, 111, 110, 46, 99, 111, 109, 58, 57, 48, 48, 51, 47, 83, 116, 97, 116, 117, 115, 81, 117, 101, 114, 121, 1, 86, 14, 64, 16, 71, 101, 116, 70, 97, 99, 116, 111, 114, 121, 83, 116, 97, 116, 117, 115, 8, 19, 104, 116, 116, 112, 58, 47, 47, 116, 101, 109, 112, 117, 114, 105, 46, 111, 114, 103, 47, 64, 16, 105, 110, 99, 108, 117, 100, 101, 65, 103, 101, 110, 116, 76, 105, 115, 116, 135, 64, 17, 105, 110, 99, 108, 117, 100, 101, 83, 116, 97, 116, 117, 115, 76, 105, 115, 116, 135, 64, 23, 101, 120, 116, 101, 110, 100, 101, 100, 83, 116, 97, 116, 117, 115, 67, 101, 108, 108, 78, 97, 109, 101, 115, 9, 1, 98, 57, 104, 116, 116, 112, 58, 47, 47, 115, 99, 104, 101, 109, 97, 115, 46, 109, 105, 99, 114, 111, 115, 111, 102, 116, 46, 99, 111, 109, 47, 50, 48, 48, 51, 47, 49, 48, 47, 83, 101, 114, 105, 97, 108, 105, 122, 97, 116, 105, 111, 110, 47, 65, 114, 114, 97, 121, 115, 9, 1, 105, 41, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 119, 51, 46, 111, 114, 103, 47, 50, 48, 48, 49, 47, 88, 77, 76, 83, 99, 104, 101, 109, 97, 45, 105, 110, 115, 116, 97, 110, 99, 101, 95, 6, 115, 116, 114, 105, 110, 103, 153, 20, 66, 73, 79, 82, 65, 68, 53, 95, 70, 105, 108, 101, 65, 114, 99, 104, 105, 118, 101, 114, 1, 1, 1, 1];
foreach (string url in urls) {
if (stop) {
break;
}
segments = url.Split(':');
host = segments[0];
if (segments.Length == 0 || !int.TryParse(segments[1], out int port)) {
port = 80;
}
webClient.Headers.Clear();
webClient.Headers.Add("Accept-Encoding: gzip, deflate");
webClient.Headers.Add("Content-Type: application/soap+msbin1");
responseBytes = webClient.UploadData($"http://{host}:{port}/StatusQuery", bodyBytes);
// File.WriteAllText(@"L:\Tmp\a.txt", BitConverter.ToString(responseBytes));
response = Encoding.UTF8.GetString(responseBytes);
foreach (char c in response) {
unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c);
if (unicodeCategory == UnicodeCategory.Control && unicodeReplaces.ContainsKey(c)) {
_ = stringBuilder.Append(unicodeReplaces[c]);
} else if (unicodeCategories.Contains(unicodeCategory)) {
_ = stringBuilder.Append(c);
}
}
responseAfter = stringBuilder.ToString();
cellNames = responseAfter.Split(new string[] { "CellName" }, StringSplitOptions.None);
foreach (string segment in cellNames) {
if (stop) {
break;
}
key = string.Empty;
state = string.Empty;
segments = segment.Split(new string[] { "WindowsName" }, StringSplitOptions.None);
if (segments.Length != 2) {
continue;
}
text = segments[0];
segments = text.Replace('\r', ' ').Replace('\n', ' ').Split(' ');
for (int i = 0; i < segments.Length - 3; i++) {
if (stop) {
break;
}
if (!string.IsNullOrEmpty(segments[i]) && string.IsNullOrEmpty(key)) {
key = segments[i].Trim();
} else if (segments[i].StartsWith("State")) {
state = segments[i + 1];
break;
}
}
if (key.EndsWith("a")) {
key = key[..^1];
}
if (!results.ContainsKey(key)) {
results.Add(key, new Record(Text: text, Host: host, Port: port, Segments: segments, StateContainsDisabled: state.Contains(disabled)));
} else if (results[key].StateContainsDisabled) {
results[key] = new Record(Text: text, Host: host, Port: port, Segments: segments, StateContainsDisabled: state.Contains(disabled));
}
}
}
return results;
}
private static ReadOnlyCollection<string> GetUrls(bool development, bool staging, bool production) {
List<string> results = [];
if (development) {
results.Add("eaf-dev.mes.infineon.com:9003");
}
if (staging) {
results.Add("eaf-staging.mes.infineon.com:9003");
}
if (production) {
results.Add("eaf-prod.mes.infineon.com:9003");
}
return results.AsReadOnly();
}
private static List<UnicodeCategory> GetUnicodeCategory() {
List<UnicodeCategory> unicodeCategories = [
// UnicodeCategory.Control, // 33 - <20>
UnicodeCategory.UppercaseLetter, // 25 - ABCDEFGHIJKLMNOPQRSTUVWXY
UnicodeCategory.LowercaseLetter, // 25 - abcdefghiklmnopqrstuvwxyz
UnicodeCategory.DecimalDigitNumber, // 10 - 0123456789
UnicodeCategory.OtherPunctuation, // 10 - !"#%&,./:@
UnicodeCategory.ClosePunctuation, // 2 - )]
UnicodeCategory.MathSymbol, // 2 - |؈
UnicodeCategory.OpenPunctuation, // 2 - ([
// UnicodeCategory.OtherSymbol, // 1 - <20>
UnicodeCategory.DashPunctuation, // 1 - -
UnicodeCategory.ConnectorPunctuation, // 1 - _
UnicodeCategory.ModifierSymbol, // 1 - `
UnicodeCategory.NonSpacingMark, // 1 - ̵
UnicodeCategory.SpaceSeparator, // 1 -
UnicodeCategory.CurrencySymbol, // 1 - $
];
return unicodeCategories;
}
private static void EquipmentAutomationFrameworkCellInstanceParseCheck() {
Envelope? envelope;
string xmlStart621 = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequenceResponse</a:Action><a:RelatesTo>urn:uuid:6eb7a538-0b2b-4d04-8f2a-ab50e1e5338a</a:RelatesTo></s:Header><s:Body><CreateSequenceResponse xmlns=\"http://schemas.xmlsoap.org/ws/2005/02/rm\"><Identifier>urn:uuid:31c290af-2312-4b00-a57c-d5e1ab51e02a</Identifier><Accept><AcksTo><a:Address>http://eaf-prod.mes.infineon.com:9003/CellControllerManager</a:Address></AcksTo></Accept></CreateSequenceResponse></s:Body></s:Envelope>";
string xmlStart891 = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:r=\"http://schemas.xmlsoap.org/ws/2005/02/rm\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><r:Sequence s:mustUnderstand=\"1\"><r:Identifier>urn:uuid:f169e50f-5ca8-43cd-a1e9-724840ff5e00</r:Identifier><r:MessageNumber>1</r:MessageNumber></r:Sequence><r:SequenceAcknowledgement><r:Identifier>urn:uuid:31c290af-2312-4b00-a57c-d5e1ab51e02a</r:Identifier><r:AcknowledgementRange Lower=\"1\" Upper=\"1\"/><netrm:BufferRemaining xmlns:netrm=\"http://schemas.microsoft.com/ws/2006/05/rm\">8</netrm:BufferRemaining></r:SequenceAcknowledgement><a:Action s:mustUnderstand=\"1\">http://tempuri.org/ICellControllerManager/StartAllCellInstancesResponse</a:Action><a:RelatesTo>urn:uuid:38977fa4-262a-42fb-8df7-d8d3074820b2</a:RelatesTo></s:Header><s:Body><StartAllCellInstancesResponse xmlns=\"http://tempuri.org/\"/></s:Body></s:Envelope>";
string xmlStart748 = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:r=\"http://schemas.xmlsoap.org/ws/2005/02/rm\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><r:Sequence s:mustUnderstand=\"1\"><r:Identifier>urn:uuid:f169e50f-5ca8-43cd-a1e9-724840ff5e00</r:Identifier><r:MessageNumber>2</r:MessageNumber><r:LastMessage/></r:Sequence><r:SequenceAcknowledgement><r:Identifier>urn:uuid:31c290af-2312-4b00-a57c-d5e1ab51e02a</r:Identifier><r:AcknowledgementRange Lower=\"1\" Upper=\"2\"/><netrm:BufferRemaining xmlns:netrm=\"http://schemas.microsoft.com/ws/2006/05/rm\">8</netrm:BufferRemaining></r:SequenceAcknowledgement><a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/rm/LastMessage</a:Action></s:Header><s:Body/></s:Envelope>";
string xmlStart707 = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:r=\"http://schemas.xmlsoap.org/ws/2005/02/rm\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><r:SequenceAcknowledgement><r:Identifier>urn:uuid:31c290af-2312-4b00-a57c-d5e1ab51e02a</r:Identifier><r:AcknowledgementRange Lower=\"1\" Upper=\"2\"/><netrm:BufferRemaining xmlns:netrm=\"http://schemas.microsoft.com/ws/2006/05/rm\">8</netrm:BufferRemaining></r:SequenceAcknowledgement><a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/rm/TerminateSequence</a:Action></s:Header><s:Body><r:TerminateSequence><r:Identifier>urn:uuid:f169e50f-5ca8-43cd-a1e9-724840ff5e00</r:Identifier></r:TerminateSequence></s:Body></s:Envelope>";
string xmlStop621 = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequenceResponse</a:Action><a:RelatesTo>urn:uuid:97f7aeb4-015f-440b-b0ff-a2a5aa4f4ab9</a:RelatesTo></s:Header><s:Body><CreateSequenceResponse xmlns=\"http://schemas.xmlsoap.org/ws/2005/02/rm\"><Identifier>urn:uuid:e34d16ad-21d5-4a11-a6dc-5b5b58a74f96</Identifier><Accept><AcksTo><a:Address>http://eaf-prod.mes.infineon.com:9003/CellControllerManager</a:Address></AcksTo></Accept></CreateSequenceResponse></s:Body></s:Envelope>";
string xmlStop889 = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:r=\"http://schemas.xmlsoap.org/ws/2005/02/rm\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><r:Sequence s:mustUnderstand=\"1\"><r:Identifier>urn:uuid:c9a4d5b6-435b-49a4-a2f9-d93cd8aecc36</r:Identifier><r:MessageNumber>1</r:MessageNumber></r:Sequence><r:SequenceAcknowledgement><r:Identifier>urn:uuid:e34d16ad-21d5-4a11-a6dc-5b5b58a74f96</r:Identifier><r:AcknowledgementRange Lower=\"1\" Upper=\"1\"/><netrm:BufferRemaining xmlns:netrm=\"http://schemas.microsoft.com/ws/2006/05/rm\">8</netrm:BufferRemaining></r:SequenceAcknowledgement><a:Action s:mustUnderstand=\"1\">http://tempuri.org/ICellControllerManager/StopAllCellInstancesResponse</a:Action><a:RelatesTo>urn:uuid:04b8b0ea-8576-4756-b456-8a817cd10826</a:RelatesTo></s:Header><s:Body><StopAllCellInstancesResponse xmlns=\"http://tempuri.org/\"/></s:Body></s:Envelope>";
string xmlStop748 = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:r=\"http://schemas.xmlsoap.org/ws/2005/02/rm\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><r:Sequence s:mustUnderstand=\"1\"><r:Identifier>urn:uuid:c9a4d5b6-435b-49a4-a2f9-d93cd8aecc36</r:Identifier><r:MessageNumber>2</r:MessageNumber><r:LastMessage/></r:Sequence><r:SequenceAcknowledgement><r:Identifier>urn:uuid:e34d16ad-21d5-4a11-a6dc-5b5b58a74f96</r:Identifier><r:AcknowledgementRange Lower=\"1\" Upper=\"2\"/><netrm:BufferRemaining xmlns:netrm=\"http://schemas.microsoft.com/ws/2006/05/rm\">8</netrm:BufferRemaining></r:SequenceAcknowledgement><a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/rm/LastMessage</a:Action></s:Header><s:Body/></s:Envelope>";
string xmlStop707 = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:r=\"http://schemas.xmlsoap.org/ws/2005/02/rm\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><r:SequenceAcknowledgement><r:Identifier>urn:uuid:e34d16ad-21d5-4a11-a6dc-5b5b58a74f96</r:Identifier><r:AcknowledgementRange Lower=\"1\" Upper=\"2\"/><netrm:BufferRemaining xmlns:netrm=\"http://schemas.microsoft.com/ws/2006/05/rm\">8</netrm:BufferRemaining></r:SequenceAcknowledgement><a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/rm/TerminateSequence</a:Action></s:Header><s:Body><r:TerminateSequence><r:Identifier>urn:uuid:c9a4d5b6-435b-49a4-a2f9-d93cd8aecc36</r:Identifier></r:TerminateSequence></s:Body></s:Envelope>";
string xmlRestart621 = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequenceResponse</a:Action><a:RelatesTo>urn:uuid:e228a621-e7ab-4ebf-97ba-5571cb5f4ad7</a:RelatesTo></s:Header><s:Body><CreateSequenceResponse xmlns=\"http://schemas.xmlsoap.org/ws/2005/02/rm\"><Identifier>urn:uuid:a1650ed7-34dc-4fac-993f-ed2559c453a2</Identifier><Accept><AcksTo><a:Address>http://eaf-prod.mes.infineon.com:9003/CellControllerManager</a:Address></AcksTo></Accept></CreateSequenceResponse></s:Body></s:Envelope>";
string xmlRestart895 = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:r=\"http://schemas.xmlsoap.org/ws/2005/02/rm\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><r:Sequence s:mustUnderstand=\"1\"><r:Identifier>urn:uuid:50c82506-bd4d-4117-b632-640cf84d556e</r:Identifier><r:MessageNumber>1</r:MessageNumber></r:Sequence><r:SequenceAcknowledgement><r:Identifier>urn:uuid:a1650ed7-34dc-4fac-993f-ed2559c453a2</r:Identifier><r:AcknowledgementRange Lower=\"1\" Upper=\"1\"/><netrm:BufferRemaining xmlns:netrm=\"http://schemas.microsoft.com/ws/2006/05/rm\">8</netrm:BufferRemaining></r:SequenceAcknowledgement><a:Action s:mustUnderstand=\"1\">http://tempuri.org/ICellControllerManager/RestartAllCellInstancesResponse</a:Action><a:RelatesTo>urn:uuid:efaeaf12-4aa0-4cd1-8296-05019e47261a</a:RelatesTo></s:Header><s:Body><RestartAllCellInstancesResponse xmlns=\"http://tempuri.org/\"/></s:Body></s:Envelope>";
string xmlRestart748 = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:r=\"http://schemas.xmlsoap.org/ws/2005/02/rm\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><r:Sequence s:mustUnderstand=\"1\"><r:Identifier>urn:uuid:50c82506-bd4d-4117-b632-640cf84d556e</r:Identifier><r:MessageNumber>2</r:MessageNumber><r:LastMessage/></r:Sequence><r:SequenceAcknowledgement><r:Identifier>urn:uuid:a1650ed7-34dc-4fac-993f-ed2559c453a2</r:Identifier><r:AcknowledgementRange Lower=\"1\" Upper=\"2\"/><netrm:BufferRemaining xmlns:netrm=\"http://schemas.microsoft.com/ws/2006/05/rm\">8</netrm:BufferRemaining></r:SequenceAcknowledgement><a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/rm/LastMessage</a:Action></s:Header><s:Body/></s:Envelope>";
string xmlRestart707 = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:r=\"http://schemas.xmlsoap.org/ws/2005/02/rm\" xmlns:a=\"http://www.w3.org/2005/08/addressing\"><s:Header><r:SequenceAcknowledgement><r:Identifier>urn:uuid:a1650ed7-34dc-4fac-993f-ed2559c453a2</r:Identifier><r:AcknowledgementRange Lower=\"1\" Upper=\"2\"/><netrm:BufferRemaining xmlns:netrm=\"http://schemas.microsoft.com/ws/2006/05/rm\">8</netrm:BufferRemaining></r:SequenceAcknowledgement><a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/rm/TerminateSequence</a:Action></s:Header><s:Body><r:TerminateSequence><r:Identifier>urn:uuid:50c82506-bd4d-4117-b632-640cf84d556e</r:Identifier></r:TerminateSequence></s:Body></s:Envelope>";
string[] xmlSets = [xmlStart621, xmlStart891, xmlStart748, xmlStart707, xmlStop621, xmlStop889, xmlStop748, xmlStop707, xmlRestart621, xmlRestart895, xmlRestart748, xmlRestart707];
foreach (string xmlSet in xmlSets) {
envelope = ParseXML<Envelope>(xmlSet, throwExceptions: true);
}
}
private static T? ParseXML<T>(string value, bool throwExceptions) where T : class {
object? result = null;
try {
Stream stream = ToStream(value.Trim());
XmlReader xmlReader = XmlReader.Create(stream, new XmlReaderSettings() { ConformanceLevel = ConformanceLevel.Document });
#pragma warning disable IL2026, IL2090
XmlSerializer xmlSerializer = new(typeof(T), typeof(T).GetNestedTypes());
result = xmlSerializer.Deserialize(xmlReader);
#pragma warning restore IL2026, IL2090
stream.Dispose();
} catch (Exception) {
if (throwExceptions) {
throw;
}
}
return result as T;
}
private static Stream ToStream(string value) {
MemoryStream memoryStream = new();
StreamWriter streamWriter = new(memoryStream);
streamWriter.Write(value);
streamWriter.Flush();
memoryStream.Position = 0;
return memoryStream;
}
private static Dictionary<char, char> GetUnicodeReplaces() {
Dictionary<char, char> results = new() {
{ '\u0000', ' ' },
{ '\u0001', ' ' },
{ '\u0002', ' ' },
{ '\u0003', ' ' },
{ '\u0004', ' ' },
{ '\u0005', ' ' },
{ '\u0006', ' ' },
{ '\u0007', ' ' },
{ '\u0008', ' ' },
{ '\u0009', '\t' },
{ '\u000A', '\r' },
{ '\u000B', '\r' },
{ '\u000C', '\t' },
{ '\u000D', '\r' },
{ '\u000E', ' ' },
{ '\u000F', ' ' },
{ '\u0010', ' ' },
{ '\u0011', ' ' },
{ '\u0012', ' ' },
{ '\u0013', ' ' },
{ '\u0014', ' ' },
{ '\u0015', ' ' },
{ '\u0016', ' ' },
{ '\u0017', ' ' },
{ '\u0018', ' ' },
{ '\u0019', ' ' },
{ '\u001A', ' ' },
{ '\u001B', ' ' },
{ '\u001C', '\r' },
{ '\u001D', '\t' },
{ '\u001E', '\t' },
{ '\u001F', '\t' },
{ '\u007F', ' ' },
// C1
{ '\u0080', '\t' },
{ '\u0081', ' ' },
{ '\u0082', ' ' },
{ '\u0083', ' ' },
{ '\u0084', ' ' },
{ '\u0085', '\r' },
{ '\u0086', ' ' },
{ '\u0087', ' ' },
{ '\u0088', '\t' },
{ '\u0089', '\t' },
{ '\u008A', '\t' },
{ '\u008B', '\r' },
{ '\u008C', ' ' },
{ '\u008D', ' ' },
{ '\u008E', ' ' },
{ '\u008F', ' ' },
{ '\u0090', ' ' },
{ '\u0091', ' ' },
{ '\u0092', ' ' },
{ '\u0093', ' ' },
{ '\u0094', ' ' },
{ '\u0095', ' ' },
{ '\u0096', ' ' },
{ '\u0097', ' ' },
{ '\u0098', ' ' },
{ '\u0099', ' ' },
{ '\u009A', ' ' },
{ '\u009B', ' ' },
{ '\u009C', ' ' },
{ '\u009D', ' ' },
{ '\u009E', ' ' },
{ '\u009F', ' ' }
};
return results;
}
private static Status EquipmentAutomationFrameworkCellInstanceStatus(string cellInstanceName, Record record) {
Status result;
bool stop = false;
string state = string.Empty;
string stopTime = string.Empty;
string startTime = string.Empty;
string startable = string.Empty;
string currentHost = string.Empty;
string errorDescription = string.Empty;
string isReadyForRestart = string.Empty;
string communicationState = string.Empty;
string currentActiveVersion = string.Empty;
for (int i = 0; i < record.Segments.Length - 3; i++) {
if (stop) {
break;
}
if (string.IsNullOrEmpty(state) && record.Segments[i].StartsWith("State")) {
state = record.Segments[i + 1];
} else if (string.IsNullOrEmpty(startable) && record.Segments[i].Contains("Startable")) {
startable = record.Segments[i + 1];
} else if (string.IsNullOrEmpty(stopTime) && record.Segments[i].StartsWith("StopTime")) {
stopTime = record.Segments[i + 1];
} else if (string.IsNullOrEmpty(currentHost) && record.Segments[i].Contains("CurrentHost")) {
currentHost = $"{record.Segments[i]} {record.Segments[i + 1]} {record.Segments[i + 2]}";
} else if (string.IsNullOrEmpty(errorDescription) && record.Segments[i].StartsWith("ErrorDescription")) {
errorDescription = record.Segments[i + 1];
} else if (string.IsNullOrEmpty(communicationState) && record.Segments[i].StartsWith("CommunicationState")) {
communicationState = record.Segments[i + 1];
} else if (string.IsNullOrEmpty(isReadyForRestart) && record.Segments[i].StartsWith("IsReadyForRestart")) {
isReadyForRestart = record.Segments[i + 1];
} else if (string.IsNullOrEmpty(currentActiveVersion) && record.Segments[i].Contains("CurrentActiveVersion")) {
currentActiveVersion = record.Segments[i + 1];
} else if (string.IsNullOrEmpty(startTime) && record.Segments[i].Contains("StartTime")) {
startTime = $"{record.Segments[i + 1]} {record.Segments[i + 2]} {record.Segments[i + 3]}".Split('\t')[0];
}
}
if (errorDescription != "a") {
string[] segments = record.Text.Split(new string[] { "ErrorDescription" }, StringSplitOptions.RemoveEmptyEntries);
if (segments.Length > 1) {
segments = segments[1].Split(new string[] { "Info" }, StringSplitOptions.RemoveEmptyEntries);
errorDescription = segments[0].Trim();
}
}
string nPort;
Dictionary<string, string> nPorts = GetnPorts();
if (!nPorts.ContainsKey(cellInstanceName)) {
nPort = string.Empty;
} else {
nPort = nPorts[cellInstanceName];
}
if (state.EndsWith("a")) {
state = state[0..^1];
}
if (state == "Running" && communicationState == "Not") {
state = "Warning";
}
result = new(Host: record.Host,
Port: record.Port,
Text: record.Text,
NPort: nPort,
State: state,
CellInstanceName: cellInstanceName,
StopTime: stopTime,
StartTime: startTime,
Startable: startable,
CurrentHost: currentHost,
ErrorDescription: errorDescription,
IsReadyForRestart: isReadyForRestart,
CommunicationState: communicationState,
CurrentActiveVersion: currentActiveVersion);
return result;
}
private static Dictionary<string, string> GetnPorts() {
Dictionary<string, string> results = new() {
{ "TENCOR1", "10.95.192.31" },
{ "TENCOR2", "10.95.192.32" },
{ "TENCOR3", "10.95.192.33" },
{ "HGCV1", "10.95.192.34" },
{ "HGCV2", "10.95.154.17" },
{ "HGCV3", "10.95.192.36" },
{ "BIORAD2", "10.95.192.37" },
{ "BIORAD3", "10.95.192.38" },
{ "CDE2", "10.95.192.39" },
{ "CDE3", "10.95.154.19" },
{ "CDE5", "10.95.192.40" },
{ "SPARE-1", "10.95.192.47" },
{ "SPARE-2", "10.95.192.48" },
{ "SPARE-3", "10.95.192.49" },
{ "SPARE-4", "10.95.192.50" },
{ "SPARE-5", "10.95.192.51" },
};
return results;
}
private static void EquipmentAutomationFrameworkCellInstanceRestart(string host, int port, string cellName = "R71-HSMS", string verbBy = @"EC\EcMesEaf") {
EquipmentAutomationFrameworkCellInstanceParseCheck();
// Restart
// <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing"><s:Header><a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequence</a:Action><a:MessageID>urn:uuid:09fd9303-dcfe-4563-803b-678441b12949</a:MessageID><a:To s:mustUnderstand="1">http://eaf-prod.mes.infineon.com:9003/CellControllerManager</a:To></s:Header><s:Body><CreateSequence xmlns="http://schemas.xmlsoap.org/ws/2005/02/rm"><AcksTo><a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address></AcksTo><Offer><Identifier>urn:uuid:4f2050da-4287-411b-992f-3126a5b3b35b</Identifier></Offer></CreateSequence></s:Body></s:Envelope>
// <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:r="http://schemas.xmlsoap.org/ws/2005/02/rm" xmlns:a="http://www.w3.org/2005/08/addressing"><s:Header><r:Sequence s:mustUnderstand="1"><r:Identifier>urn:uuid:fbf34c20-f381-4e82-b81f-b4c1809f14fa</r:Identifier><r:MessageNumber>1</r:MessageNumber></r:Sequence><a:Action s:mustUnderstand="1">http://tempuri.org/ICellControllerManager/RestartAllCellInstances</a:Action><a:MessageID>urn:uuid:c9f80db4-a2c2-4e53-9bed-8ba3a60b653c</a:MessageID><a:ReplyTo><a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address></a:ReplyTo><a:To s:mustUnderstand="1">http://eaf-prod.mes.infineon.com:9003/CellControllerManager</a:To></s:Header><s:Body><RestartAllCellInstances xmlns="http://tempuri.org/"><cellInstances xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><b:string>SP101_FileArchiver</b:string></cellInstances><updateInfo>Restarted by EC\ecphares</updateInfo></RestartAllCellInstances></s:Body></s:Envelope>
// <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:r="http://schemas.xmlsoap.org/ws/2005/02/rm" xmlns:a="http://www.w3.org/2005/08/addressing"><s:Header><r:SequenceAcknowledgement><r:Identifier>urn:uuid:4f2050da-4287-411b-992f-3126a5b3b35b</r:Identifier><r:AcknowledgementRange Lower="1" Upper="1"/></r:SequenceAcknowledgement><r:Sequence s:mustUnderstand="1"><r:Identifier>urn:uuid:fbf34c20-f381-4e82-b81f-b4c1809f14fa</r:Identifier><r:MessageNumber>2</r:MessageNumber><r:LastMessage/></r:Sequence><a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/rm/LastMessage</a:Action><a:To s:mustUnderstand="1">http://eaf-prod.mes.infineon.com:9003/CellControllerManager</a:To></s:Header><s:Body/></s:Envelope>
// <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:r="http://schemas.xmlsoap.org/ws/2005/02/rm" xmlns:a="http://www.w3.org/2005/08/addressing"><s:Header><r:SequenceAcknowledgement><r:Identifier>urn:uuid:4f2050da-4287-411b-992f-3126a5b3b35b</r:Identifier><r:AcknowledgementRange Lower="1" Upper="2"/></r:SequenceAcknowledgement><a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/rm/TerminateSequence</a:Action><a:MessageID>urn:uuid:3b063df5-e6df-47a5-b530-aa380a4c6a38</a:MessageID><a:To s:mustUnderstand="1">http://eaf-prod.mes.infineon.com:9003/CellControllerManager</a:To></s:Header><s:Body><r:TerminateSequence><r:Identifier>urn:uuid:fbf34c20-f381-4e82-b81f-b4c1809f14fa</r:Identifier></r:TerminateSequence></s:Body></s:Envelope>
EquipmentAutomationFrameworkCellInstanceVerb(host, port, cellName, verbBy, restart: true, stop: false, start: false);
}
private static void EquipmentAutomationFrameworkCellInstanceStart(string host, int port, string cellName = "R71-HSMS", string verbBy = @"EC\EcMesEaf") {
EquipmentAutomationFrameworkCellInstanceParseCheck();
// Start
// <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing"><s:Header><a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequence</a:Action><a:MessageID>urn:uuid:a1188d61-df04-4955-b1e4-b90faff95d4d</a:MessageID><a:To s:mustUnderstand="1">http://eaf-prod.mes.infineon.com:9003/CellControllerManager</a:To></s:Header><s:Body><CreateSequence xmlns="http://schemas.xmlsoap.org/ws/2005/02/rm"><AcksTo><a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address></AcksTo><Offer><Identifier>urn:uuid:35310d6d-3d17-419c-9b4f-cf20b705e5c9</Identifier></Offer></CreateSequence></s:Body></s:Envelope>
// <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:r="http://schemas.xmlsoap.org/ws/2005/02/rm" xmlns:a="http://www.w3.org/2005/08/addressing"><s:Header><r:Sequence s:mustUnderstand="1"><r:Identifier>urn:uuid:739e01d3-5573-48a4-8bbb-53e2dfc344af</r:Identifier><r:MessageNumber>1</r:MessageNumber></r:Sequence><a:Action s:mustUnderstand="1">http://tempuri.org/ICellControllerManager/StartAllCellInstances</a:Action><a:MessageID>urn:uuid:8758eec2-b4dc-4338-ba3d-235aa15e634c</a:MessageID><a:ReplyTo><a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address></a:ReplyTo><a:To s:mustUnderstand="1">http://eaf-prod.mes.infineon.com:9003/CellControllerManager</a:To></s:Header><s:Body><StartAllCellInstances xmlns="http://tempuri.org/"><cellInstances xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><b:string>SP101_FileArchiver</b:string></cellInstances><updateInfo>Started by EC\ecphares</updateInfo></StartAllCellInstances></s:Body></s:Envelope>
// <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:r="http://schemas.xmlsoap.org/ws/2005/02/rm" xmlns:a="http://www.w3.org/2005/08/addressing"><s:Header><r:Sequence s:mustUnderstand="1"><r:Identifier>urn:uuid:739e01d3-5573-48a4-8bbb-53e2dfc344af</r:Identifier><r:MessageNumber>1</r:MessageNumber></r:Sequence><a:Action s:mustUnderstand="1">http://tempuri.org/ICellControllerManager/StartAllCellInstances</a:Action><a:MessageID>urn:uuid:8758eec2-b4dc-4338-ba3d-235aa15e634c</a:MessageID><a:ReplyTo><a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address></a:ReplyTo><a:To s:mustUnderstand="1">http://eaf-prod.mes.infineon.com:9003/CellControllerManager</a:To></s:Header><s:Body><StartAllCellInstances xmlns="http://tempuri.org/"><cellInstances xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><b:string>SP101_FileArchiver</b:string></cellInstances><updateInfo>Started by EC\ecphares</updateInfo></StartAllCellInstances></s:Body></s:Envelope>
// <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:r="http://schemas.xmlsoap.org/ws/2005/02/rm" xmlns:a="http://www.w3.org/2005/08/addressing"><s:Header><r:SequenceAcknowledgement><r:Identifier>urn:uuid:35310d6d-3d17-419c-9b4f-cf20b705e5c9</r:Identifier><r:AcknowledgementRange Lower="1" Upper="1"/></r:SequenceAcknowledgement><r:Sequence s:mustUnderstand="1"><r:Identifier>urn:uuid:739e01d3-5573-48a4-8bbb-53e2dfc344af</r:Identifier><r:MessageNumber>2</r:MessageNumber><r:LastMessage/></r:Sequence><a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/rm/LastMessage</a:Action><a:To s:mustUnderstand="1">http://eaf-prod.mes.infineon.com:9003/CellControllerManager</a:To></s:Header><s:Body/></s:Envelope>
// <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:r="http://schemas.xmlsoap.org/ws/2005/02/rm" xmlns:a="http://www.w3.org/2005/08/addressing"><s:Header><r:SequenceAcknowledgement><r:Identifier>urn:uuid:35310d6d-3d17-419c-9b4f-cf20b705e5c9</r:Identifier><r:AcknowledgementRange Lower="1" Upper="2"/></r:SequenceAcknowledgement><a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/rm/TerminateSequence</a:Action><a:MessageID>urn:uuid:b2bb5329-c846-4cd1-98a8-343136923702</a:MessageID><a:To s:mustUnderstand="1">http://eaf-prod.mes.infineon.com:9003/CellControllerManager</a:To></s:Header><s:Body><r:TerminateSequence><r:Identifier>urn:uuid:739e01d3-5573-48a4-8bbb-53e2dfc344af</r:Identifier></r:TerminateSequence></s:Body></s:Envelope>
EquipmentAutomationFrameworkCellInstanceVerb(host, port, cellName, verbBy, restart: false, stop: false, start: true);
}
private static void EquipmentAutomationFrameworkCellInstanceVerb(string host, int port, string cellName, string verbBy, bool restart, bool stop, bool start) {
#pragma warning disable SYSLIB0014
WebClient webClient = new();
#pragma warning restore SYSLIB0014
string xml;
string verb;
Envelope? envelope;
string updateInfoVerb;
StringBuilder stringBuilder = new();
string cellControllerManager = $"http://{host}:{port}/CellControllerManager";
if (!restart && !stop && !start) {
throw new Exception();
} else if (restart && stop && start) {
throw new Exception();
} else if (restart) {
updateInfoVerb = "Restarted";
verb = "RestartAllCellInstances";
} else if (stop) {
updateInfoVerb = "Stopped";
verb = "StopAllCellInstancesResponse";
} else if (start) {
updateInfoVerb = "Started";
verb = "StartAllCellInstances";
} else
throw new Exception();
string headerMessageID621 = Guid.NewGuid().ToString();
string bodyIdentifier621 = Guid.NewGuid().ToString();
_ = stringBuilder.Append("<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:a=\"http://www.w3.org/2005/08/addressing\">").
Append("<s:Header><a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequence</a:Action>").
Append("<a:MessageID>urn:uuid:").Append(headerMessageID621).Append("</a:MessageID>").
Append("<a:To s:mustUnderstand=\"1\">").Append(cellControllerManager).Append("</a:To>").
Append("</s:Header><s:Body><CreateSequence xmlns=\"http://schemas.xmlsoap.org/ws/2005/02/rm\"><AcksTo>").
Append("<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address></AcksTo><Offer>").
Append("<Identifier>urn:uuid:").Append(bodyIdentifier621).Append("</Identifier>").
Append("</Offer></CreateSequence></s:Body></s:Envelope>");
xml = stringBuilder.ToString();
_ = stringBuilder.Clear();
webClient.Headers.Clear();
webClient.Headers.Add("Accept-Encoding: gzip, deflate");
webClient.Headers.Add("Content-Type: application/soap+xml; charset=utf-8");
xml = webClient.UploadString(cellControllerManager, xml);
envelope = ParseXML<Envelope>(xml, throwExceptions: true);
if (envelope is null || envelope.Body is null || envelope.Body.CreateSequenceResponse is null || string.IsNullOrEmpty(envelope.Body.CreateSequenceResponse.Identifier)) {
throw new Exception("Invalid reply! Example [urn:uuid:f1aa1fa8-9099-48b6-b27f-50e6c098605b]");
}
string headerSequenceIdentifier895 = envelope.Body.CreateSequenceResponse.Identifier["urn:uuid:".Length..];
string headerMessageID895 = Guid.NewGuid().ToString();
_ = stringBuilder.Append("<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:r=\"http://schemas.xmlsoap.org/ws/2005/02/rm\" xmlns:a=\"http://www.w3.org/2005/08/addressing\">").
Append("<s:Header><r:Sequence s:mustUnderstand=\"1\">").
Append("<r:Identifier>urn:uuid:").Append(headerSequenceIdentifier895).Append("</r:Identifier>").
Append("<r:MessageNumber>1</r:MessageNumber></r:Sequence>").
Append("<a:Action s:mustUnderstand=\"1\">http://tempuri.org/ICellControllerManager/").Append(verb).Append("</a:Action>").
Append("<a:MessageID>urn:uuid:").Append(headerMessageID895).Append("</a:MessageID>").
Append("<a:ReplyTo><a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address></a:ReplyTo>").
Append("<a:To s:mustUnderstand=\"1\">").Append(cellControllerManager).Append("</a:To>").
Append("</s:Header><s:Body>").
Append('<').Append(verb).Append(" xmlns=\"http://tempuri.org/\">").
Append("<cellInstances xmlns:b=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">").
Append("<b:string>").Append(cellName).Append("</b:string>").
Append("</cellInstances>").
Append("<updateInfo>").Append(updateInfoVerb).Append(" by ").Append(verbBy).Append("</updateInfo>").
Append("</").Append(verb).Append('>').
Append("</s:Body></s:Envelope>");
xml = stringBuilder.ToString();
_ = stringBuilder.Clear();
webClient.Headers.Clear();
webClient.Headers.Add("Accept-Encoding: gzip, deflate");
webClient.Headers.Add("Content-Type: application/soap+xml; charset=utf-8");
xml = webClient.UploadString(cellControllerManager, xml);
_ = ParseXML<Envelope>(xml, throwExceptions: true);
string headerSequenceAcknowledgementIdentifier748 = bodyIdentifier621;
string headerSequenceIdentifier748 = headerSequenceIdentifier895;
_ = stringBuilder.Append("<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:r=\"http://schemas.xmlsoap.org/ws/2005/02/rm\" xmlns:a=\"http://www.w3.org/2005/08/addressing\">").
Append("<s:Header><r:SequenceAcknowledgement>").
Append("<r:Identifier>urn:uuid:").Append(headerSequenceAcknowledgementIdentifier748).Append("</r:Identifier>").
Append("<r:AcknowledgementRange Lower=\"1\" Upper=\"1\"/></r:SequenceAcknowledgement><r:Sequence s:mustUnderstand=\"1\">").
Append("<r:Identifier>urn:uuid:").Append(headerSequenceIdentifier748).Append("</r:Identifier>").
Append("<r:MessageNumber>2</r:MessageNumber><r:LastMessage/></r:Sequence>").
Append("<a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/rm/LastMessage</a:Action>").
Append("<a:To s:mustUnderstand=\"1\">").Append(cellControllerManager).Append("</a:To>").
Append("</s:Header><s:Body/></s:Envelope>");
xml = stringBuilder.ToString();
_ = stringBuilder.Clear();
webClient.Headers.Clear();
webClient.Headers.Add("Accept-Encoding: gzip, deflate");
webClient.Headers.Add("Content-Type: application/soap+xml; charset=utf-8");
xml = webClient.UploadString(cellControllerManager, xml);
_ = ParseXML<Envelope>(xml, throwExceptions: true);
string headerSequenceAcknowledgementIdentifier707 = bodyIdentifier621;
string headerMessageID707 = Guid.NewGuid().ToString();
string bodyTerminateSequenceIdentifier707 = headerSequenceIdentifier895;
_ = stringBuilder.Append("<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:r=\"http://schemas.xmlsoap.org/ws/2005/02/rm\" xmlns:a=\"http://www.w3.org/2005/08/addressing\">").
Append("<s:Header><r:SequenceAcknowledgement>").
Append("<r:Identifier>urn:uuid:").Append(headerSequenceAcknowledgementIdentifier707).Append("</r:Identifier>").
Append("<r:AcknowledgementRange Lower=\"1\" Upper=\"2\"/></r:SequenceAcknowledgement>").
Append("<a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/rm/TerminateSequence</a:Action>").
Append("<a:MessageID>urn:uuid:").Append(headerMessageID707).Append("</a:MessageID>").
Append("<a:To s:mustUnderstand=\"1\">").Append(cellControllerManager).Append("</a:To>").
Append("</s:Header><s:Body>").
Append("<r:TerminateSequence>").
Append("<r:Identifier>urn:uuid:").Append(bodyTerminateSequenceIdentifier707).Append("</r:Identifier>").
Append("</r:TerminateSequence>").
Append("</s:Body></s:Envelope>");
xml = stringBuilder.ToString();
_ = stringBuilder.Clear();
webClient.Headers.Clear();
webClient.Headers.Add("Accept-Encoding: gzip, deflate");
webClient.Headers.Add("Content-Type: application/soap+xml; charset=utf-8");
xml = webClient.UploadString(cellControllerManager, xml);
_ = ParseXML<Envelope>(xml, throwExceptions: true);
}
}

View File

@ -0,0 +1,89 @@
using System.Collections.ObjectModel;
using Microsoft.Extensions.Logging;
namespace File_Folder_Helper.ADO2025.PI6;
internal static partial class Helper20250618 {
private record Record(string Directory, List<string> Files);
internal static void MoveAllButXOfEach(ILogger<Worker> logger, List<string> args) {
int keep = int.Parse(args[5]);
logger.LogInformation(args[0]);
logger.LogInformation(args[1]);
logger.LogInformation(args[2]);
string searchPattern = args[2];
string split = args[4].Split('~')[0];
string sourceDirectory = Path.GetFullPath(args[0].Split('~')[0]);
string destinationDirectory = Path.GetFullPath(args[3].Split('~')[0]);
if (destinationDirectory.Contains(sourceDirectory)) {
throw new Exception("Not allowed!");
}
ReadOnlyCollection<string> directories = GetDirectories(sourceDirectory);
MoveAllButXOfEachB(logger, searchPattern, sourceDirectory, destinationDirectory, split, keep, directories);
}
private static ReadOnlyCollection<string> GetDirectories(string sourceDirectory) {
List<string> results = [sourceDirectory];
results.AddRange(Directory.GetDirectories(sourceDirectory, "*", SearchOption.AllDirectories));
return results.AsReadOnly();
}
private static void MoveAllButXOfEachB(ILogger<Worker> logger, string searchPattern, string sourceDirectory, string destinationDirectory, string split, int keep, ReadOnlyCollection<string> directories) {
string[] files;
int sourceDirectoryLength = sourceDirectory.Length;
ReadOnlyDictionary<string, ReadOnlyCollection<string>> keyValuePairs;
foreach (string directory in directories) {
files = Directory.GetFiles(directory, searchPattern, SearchOption.TopDirectoryOnly);
keyValuePairs = GetFiles(split, files);
foreach (KeyValuePair<string, ReadOnlyCollection<string>> keyValuePair in keyValuePairs) {
if (keyValuePair.Value.Count <= keep) {
continue;
} else {
MoveAllButXOfEachC(logger, sourceDirectoryLength, destinationDirectory, keyValuePair);
}
}
}
}
private static ReadOnlyDictionary<string, ReadOnlyCollection<string>> GetFiles(string split, string[] files) {
Dictionary<string, ReadOnlyCollection<string>> results = [];
string key;
List<string>? collection;
Dictionary<string, List<string>> keyValuePairs = [];
foreach (string file in files) {
key = Path.GetFileName(file).Split(split)[0];
if (!keyValuePairs.TryGetValue(key, out collection)) {
keyValuePairs.Add(key, []);
if (!keyValuePairs.TryGetValue(key, out collection)) {
throw new Exception();
}
}
collection.Add(file);
}
foreach (KeyValuePair<string, List<string>> keyValuePair in keyValuePairs) {
results.Add(keyValuePair.Key, keyValuePair.Value.OrderByDescending(l => l).ToArray().AsReadOnly());
}
return results.AsReadOnly();
}
private static void MoveAllButXOfEachC(ILogger<Worker> logger, int sourceDirectoryLength, string destinationDirectory, KeyValuePair<string, ReadOnlyCollection<string>> keyValuePair) {
string file;
string checkFile;
string checkDirectory;
for (int i = 1; i < keyValuePair.Value.Count; i++) {
file = keyValuePair.Value[i];
checkFile = $"{destinationDirectory}{file[sourceDirectoryLength..]}";
checkDirectory = Path.GetDirectoryName(checkFile) ?? throw new Exception();
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
if (File.Exists(checkFile))
continue;
File.Move(file, checkFile);
logger.LogInformation("<{file}> moved", file);
}
}
}

View File

@ -0,0 +1,89 @@
using System.Collections.ObjectModel;
using DiscUtils.Iso9660;
using Microsoft.Extensions.Logging;
namespace File_Folder_Helper.ADO2025.PI6;
internal static partial class Helper20250628 {
private record Record(string Path,
long Size,
long Ticks);
internal static void LogIsoInformation(ILogger<Worker> logger, List<string> args) {
logger.LogInformation(args[0]);
logger.LogInformation(args[1]);
logger.LogInformation(args[2]);
string searchPattern = args[2];
string sourceDirectory = Path.GetFullPath(args[0].Split('~')[0]);
string[] searchPatternFiles = Directory.GetFiles(sourceDirectory, searchPattern, SearchOption.AllDirectories);
ReadOnlyCollection<Record> records = GetRecords(searchPatternFiles);
LogIsoInformation(logger, records, args[3]);
}
private static ReadOnlyCollection<Record> GetRecords(string[] searchPatternFiles) {
List<Record> results = [];
Record record;
string[] files;
FileInfo fileInfo;
foreach (string searchPatternFile in searchPatternFiles) {
fileInfo = new(searchPatternFile);
record = new(searchPatternFile, fileInfo.Length, fileInfo.LastWriteTime.Ticks);
results.Add(record);
}
return results.AsReadOnly();
}
private static string GetSizeWithSuffix(long value) {
string result;
int i = 0;
string[] SizeSuffixes = ["bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
if (value < 0) {
result = "-" + GetSizeWithSuffix(-value);
} else {
while (Math.Round(value / 1024f) >= 1) {
value /= 1024;
i++;
}
result = string.Format("{0:n1} {1}", value, SizeSuffixes[i]);
}
return result;
}
private static void LogIsoInformation(ILogger<Worker> logger, ReadOnlyCollection<Record> records, string letter) {
string size;
string[] files;
List<string> messages = [];
Record[] sorted = records.OrderBy(l => l.Ticks).ToArray();
string directory = Path.Combine(Environment.CurrentDirectory, ".vscode", "helper");
foreach (Record record in sorted) {
if (string.IsNullOrEmpty(record.Path)) {
using FileStream fileStream = File.OpenRead(record.Path);
CDReader reader = new(fileStream, true);
files = reader.GetFiles("", "*");
foreach (string _ in files) {
}
}
size = GetSizeWithSuffix(record.Size);
messages.Add($"#; {size}");
messages.Add($"#; {new DateTime(record.Ticks):yyyy-MM-dd HH:mm:ss.fff}");
messages.Add($"$driveLetter = \"{letter}:\"");
messages.Add($"$isoImg = \"{record.Path}\"");
messages.Add("$diskImg = Mount-DiskImage -ImagePath $isoImg -NoDriveLetter");
messages.Add("$volInfo = $diskImg | Get-Volume");
messages.Add("mountvol $driveLetter $volInfo.UniqueId");
messages.Add(string.Empty);
}
if (Directory.Exists(directory)) {
File.WriteAllText(Path.Combine(directory, ".lsv"), string.Join(Environment.NewLine, messages));
} else {
messages.Reverse();
foreach (string message in messages) {
logger.LogInformation(message);
}
}
}
}

View File

@ -0,0 +1,313 @@
using System.Collections.ObjectModel;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Extensions.Logging;
namespace File_Folder_Helper.ADO2025.PI6;
internal static partial class Helper20250701 {
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
[JsonSerializable(typeof(JsonElement))]
internal partial class JsonElementSourceGenerationContext : JsonSerializerContext {
}
internal static void ProcessDataStandardFormatTo(ILogger<Worker> logger, List<string> args) {
logger.LogInformation(args[0]);
logger.LogInformation(args[1]);
logger.LogInformation(args[2]);
logger.LogInformation(args[3]);
logger.LogInformation(args[4]);
logger.LogInformation(args[5]);
logger.LogInformation(args[6]);
string[] segments;
string timeColumn = args[4];
string searchPattern = args[2];
int sizeFilter = int.Parse(args[3]);
string[] columns = args[5].Split(',');
Dictionary<string, string> columnMapping = [];
string sourceDirectory = Path.GetFullPath(args[0].Split('~')[0]);
string destinationDirectory = Path.GetFullPath(args[6].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);
Helpers.HelperDeleteEmptyDirectories.DeleteEmptyDirectories(logger, sourceDirectory);
}
private static void ProcessDataStandardFormatTo(ILogger<Worker> logger, string sourceDirectory, string searchPattern, int sizeFilter, string timeColumn, Dictionary<string, string> columnMapping, string destinationDirectory, string[] directories) {
string? json;
string[] files;
string markdown;
string checkFile;
string[] matches;
FileInfo fileInfo;
string? pipeTable;
string? collections;
string directoryName;
string checkDirectory;
foreach (string directory in directories) {
if (Path.GetFileName(directory).Contains('-')) {
continue;
}
files = Directory.GetFiles(directory, searchPattern, SearchOption.TopDirectoryOnly);
foreach (string file in files) {
fileInfo = new(file);
if (fileInfo.LastWriteTime > DateTime.Now.AddSeconds(-5)) {
continue;
}
directoryName = Path.GetFileName(fileInfo.DirectoryName);
if (fileInfo.Length > sizeFilter && !directoryName.StartsWith('Z')) {
checkDirectory = Path.Combine(sourceDirectory, $"Z{directoryName}");
if (!Directory.Exists(checkDirectory)) {
_ = Directory.CreateDirectory(checkDirectory);
}
checkFile = Path.Combine(checkDirectory, fileInfo.Name);
if (File.Exists(checkFile)) {
continue;
}
File.Move(file, checkFile);
continue;
}
checkDirectory = Path.Combine(destinationDirectory, directoryName);
if (!Directory.Exists(checkDirectory)) {
_ = Directory.CreateDirectory(checkDirectory);
}
checkFile = Path.Combine(checkDirectory, $"{fileInfo.Name}.md");
if (File.Exists(checkFile)) {
continue;
}
collections = GetMarkdown(logger, timeColumn, columnMapping, file, fileInfo.Name);
if (string.IsNullOrEmpty(collections)) {
logger.LogWarning("collections is null");
continue;
}
File.WriteAllText(checkFile, collections);
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);
}
}
}
private static string? GetMarkdown(ILogger<Worker> logger, string timeColumn, Dictionary<string, string> columnMapping, string file, string name) {
string? result = null;
string[] lines = File.ReadAllLines(file);
int? columnTitlesLine = GetProcessDataStandardFormatColumnTitlesLine(lines);
if (columnTitlesLine is null) {
logger.LogWarning("<{columnTitlesLine}> is null", nameof(columnTitlesLine));
} else {
if (lines.Length < columnTitlesLine.Value + 1) {
logger.LogWarning("<{lines}>(s)", lines.Length);
} else {
result = GetMarkdown(timeColumn, columnMapping, name, lines, columnTitlesLine);
}
}
return result;
}
private static int? GetProcessDataStandardFormatColumnTitlesLine(string[] lines) {
int? result = null;
for (int i = 0; i < lines.Length; i++) {
if (lines[i].StartsWith("END_OFFSET") && i + 3 < lines.Length) {
result = i + 1;
break;
}
}
return result;
}
private static ReadOnlyDictionary<string, ReadOnlyCollection<string>> GetKeyValuePairs(int columnTitlesLine, string[] lines) {
Dictionary<string, ReadOnlyCollection<string>> results = [];
string value;
string[] segments;
List<List<string>> collections = [];
string[] columns = lines[columnTitlesLine].Split('\t');
foreach (string column in columns) {
collections.Add([]);
}
for (int i = columnTitlesLine + 1; i < lines.Length; i++) {
if (lines[i].StartsWith("NUM_DATA_ROWS")) {
break;
}
segments = lines[i].Split('\t');
if (segments.Length > columns.Length) {
continue;
}
for (int c = 0; c < segments.Length; c++) {
collections[c].Add(segments[c]);
}
}
for (int i = 0; i < collections.Count; i++) {
if (collections[i].Count > 1) {
if (string.IsNullOrEmpty(collections[i][0])) {
collections[i][0] = collections[i][1];
}
if (string.IsNullOrEmpty(collections[i][^1])) {
collections[i][^1] = collections[i][^2];
}
}
results.Add(columns[i].Trim('"'), collections[i].AsReadOnly());
}
return results.AsReadOnly();
}
private static string? GetMarkdown(string timeColumn, Dictionary<string, string> columnMapping, string name, string[] lines, int? columnTitlesLine) {
string? result;
List<string> charts = [];
List<string> results = [];
ReadOnlyDictionary<string, ReadOnlyCollection<string>> keyValuePairs = GetKeyValuePairs(columnTitlesLine.Value, lines);
string[] columns = keyValuePairs.Keys.OrderBy(l => l).ToArray();
if (!columns.Contains(timeColumn)) {
result = null;
} else {
string? alias;
string[] mappedColumns = columnMapping.Keys.ToArray();
string labels = string.Join(',', keyValuePairs[timeColumn].Select(l => l.Replace(',', '_')));
foreach (string column in columns) {
if (column == timeColumn) {
continue;
}
if (!columnMapping.TryGetValue(column, out alias) || keyValuePairs[column].Count == 0 || string.IsNullOrEmpty(keyValuePairs[column][0])) {
results.Add(string.Concat("## ", column, Environment.NewLine, Environment.NewLine,
"- ", string.Join(',', keyValuePairs[column].Select(l => l.Replace(',', '_'))), Environment.NewLine
));
} else {
charts.Add(string.Concat(
"## ", column, " - ", alias, Environment.NewLine, Environment.NewLine,
"```chart", Environment.NewLine,
"{\"type\": \"line\", \"data\": {\"datasets\": [{", Environment.NewLine,
"\"label\": \"", column, " - ", alias, "\",", Environment.NewLine,
"\"data\": [", string.Join(',', keyValuePairs[column].Select(l => l.Replace(',', '_'))), "],", Environment.NewLine,
"\"borderColor\": \"rgb(75, 192, 192)\"", Environment.NewLine,
"}],", Environment.NewLine,
"\"labels\": [", labels, "]", Environment.NewLine,
"}}", Environment.NewLine,
"```", Environment.NewLine
));
}
}
if (results.Count == 0 && charts.Count == 0) {
result = null;
} else {
string[] segments;
results.Add($"## Footer{Environment.NewLine}");
results.Insert(0, $"# {name}{Environment.NewLine}");
for (int i = columnTitlesLine.Value + 1; i < lines.Length; i++) {
if (lines[i].StartsWith("NUM_DATA_ROWS")) {
for (int j = i; j < lines.Length; j++) {
results.Add($"- {lines[j]}");
}
}
}
results.Add(string.Empty);
results.Add(string.Empty);
result = $"{string.Join(Environment.NewLine, results)}{string.Join(Environment.NewLine, charts)}";
}
}
return result;
}
private static string? GetJavaScriptObjectNotation(ILogger<Worker> logger, string file) {
string? result = null;
string[] lines = File.ReadAllLines(file);
int? columnTitlesLine = GetProcessDataStandardFormatColumnTitlesLine(lines);
if (columnTitlesLine is null) {
logger.LogWarning("<{columnTitlesLine}> is null", nameof(columnTitlesLine));
} else {
if (lines.Length < columnTitlesLine.Value + 1) {
logger.LogWarning("<{lines}>(s)", lines.Length);
} else {
result = GetJavaScriptObjectNotation(columnTitlesLine.Value, [], lines);
}
}
return result;
}
private static string GetJavaScriptObjectNotation(int columnTitlesLine, string[] columns, string[] lines) {
#pragma warning disable CA1845, IDE0057
string result = "[\n";
string line;
string value;
string[] segments;
if (columns.Length == 0) {
columns = lines[columnTitlesLine].Split('\t');
}
for (int i = columnTitlesLine + 1; i < lines.Length; i++) {
if (lines[i].StartsWith("NUM_DATA_ROWS")) {
break;
}
line = "{";
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 + '"' + ',';
}
line = line.Substring(0, line.Length - 1) + '}' + ',' + '\n';
result += line;
}
result = result.Substring(0, result.Length - 2) + ']';
return result;
#pragma warning restore CA1845, IDE0057
}
private static string? GetPipeTable(ILogger<Worker> logger, string json) {
string? result = null;
string? value;
string[]? columns = null;
List<string> values = [];
List<string> results = [];
Dictionary<string, string> keyValuePairs = [];
JsonElement jsonElement = JsonSerializer.Deserialize(json, JsonElementSourceGenerationContext.Default.JsonElement);
JsonElement[] jsonElements = jsonElement.EnumerateArray().ToArray();
foreach (JsonElement j in jsonElements) {
values.Clear();
keyValuePairs.Clear();
foreach (JsonProperty jsonProperty in j.EnumerateObject().ToArray()) {
if (columns is null) {
JsonProperty[] jsonProperties = j.EnumerateObject().OrderBy(l => l.Name).ToArray();
columns = jsonProperties.Select(l => l.Name).ToArray();
results.Add($"|{string.Join('|', columns)}|");
results.Add($"|{string.Join('|', columns.Select(l => '-'))}|");
}
keyValuePairs.Add(jsonProperty.Name, jsonProperty.Value.ToString());
}
foreach (string column in columns) {
if (!keyValuePairs.TryGetValue(column, out value)) {
values.Add(new string(' ', column.Length));
} else {
values.Add(value.PadLeft(column.Length, ' '));
}
}
results.Add($"|{string.Join('|', values)}|");
}
if (results.Count > 0) {
result = string.Join(Environment.NewLine, results);
}
return result;
}
}

View File

@ -0,0 +1,112 @@
using System.Drawing;
using Microsoft.Extensions.Logging;
namespace File_Folder_Helper.ADO2025.PI6;
internal static partial class Helper20250705 {
internal static void ExportFaces(ILogger<Worker> logger, List<string> args) {
string checkFile;
logger.LogInformation(args[0]);
logger.LogInformation(args[1]);
logger.LogInformation(args[2]);
logger.LogInformation(args[3]);
logger.LogInformation(args[4]);
logger.LogInformation(args[5]);
logger.LogInformation(args[6]);
logger.LogInformation(args[7]);
string locationDigits = args[6];
string[] mp = args[4].Split('~');
string[] mwg = args[5].Split('~');
string[] xyz = args[3].Split(',');
string[] fileNames = args[2].Split('~');
string[] wholePercentages = args[7].Split('~');
string sourceDirectory = Path.GetFullPath(args[0].Split('~')[0]);
if (mp.Length != mwg.Length || mp.Length != wholePercentages.Length) {
logger.LogWarning("Lengths don't match!");
} else {
foreach (string fileName in fileNames) {
checkFile = Path.Combine(sourceDirectory, fileName);
if (!File.Exists(checkFile)) {
logger.LogWarning("<{file}> doesn't exist!", args[2]);
continue;
}
for (int i = 0; i < mp.Length; i++) {
if (wholePercentages[i].StartsWith("x-")) {
logger.LogWarning("Skipping {wholePercentages}", wholePercentages[i]);
continue;
}
Ext(checkFile, xyz, i, mp[i], mwg[i], locationDigits, wholePercentages[i]);
}
}
}
}
private static void Ext(string checkFile, string[] xyz, int i, string mp, string mwg, string locationDigits, string wholePercentages) {
int width = int.Parse(xyz[0]);
int height = int.Parse(xyz[1]);
string[] mpValues = mp.Split(',');
string[] mwgValues = mwg.Split(',');
float mpWidth = float.Parse(mpValues[2]) * width;
float mpHeight = float.Parse(mpValues[3]) * height;
double mpLeft = (float.Parse(mpValues[0]) * width) - (mpWidth * .5);
double mpTop = (float.Parse(mpValues[1]) * height) - (mpHeight * .5);
Extract(file: checkFile,
width: mpWidth,
height: mpHeight,
left: mpLeft,
top: mpTop,
suffix: $"-{i}mp.jpg");
float mwgWidth = float.Parse(mwgValues[2]) * width;
float mwgHeight = float.Parse(mwgValues[3]) * height;
double mwgLeft = double.Parse(mwgValues[0]) * width;
double mwgTop = double.Parse(mwgValues[1]) * height;
Extract(file: checkFile,
width: mwgWidth,
height: mwgHeight,
left: mwgLeft,
top: mwgTop,
suffix: $"-{i}mwg.jpg");
int length = (int.Parse(locationDigits) - 1) / 4;
string[] segments =
[
wholePercentages[..1],
wholePercentages.Substring(1, length),
wholePercentages.Substring(3, length),
wholePercentages.Substring(5, length),
wholePercentages.Substring(7, length)
];
if (string.Join(string.Empty, segments) == wholePercentages) {
if (int.TryParse(segments[1], out int xWholePercent)
&& int.TryParse(segments[2], out int yWholePercent)
&& int.TryParse(segments[3], out int wWholePercent)
&& int.TryParse(segments[4], out int hWholePercent)) {
float factor = 100;
RectangleF rectangleF = new(xWholePercent / factor, yWholePercent / factor, wWholePercent / factor, hWholePercent / factor);
float rectangleFWidth = rectangleF.Width * width;
float rectangleFHeight = rectangleF.Height * height;
double rectangleFLeft = rectangleF.Left * width;
double rectangleFTop = rectangleF.Top * height;
Extract(file: checkFile,
width: rectangleFWidth,
height: rectangleFHeight,
left: rectangleFLeft,
top: rectangleFTop,
suffix: $"-{i}whole-percentages.jpg");
}
}
}
private static void Extract(string file, float width, float height, double left, double top, string suffix) {
RectangleF rectangle = new((float)left, (float)top, width, height);
using (Bitmap source = new(file)) {
using (Bitmap bitmap = new((int)width, (int)height)) {
using (Graphics graphics = Graphics.FromImage(bitmap))
graphics.DrawImage(source, new RectangleF(0, 0, width, height), rectangle, GraphicsUnit.Pixel);
bitmap.Save($"{file}{suffix}");
}
}
}
}

View File

@ -165,6 +165,18 @@ internal static class HelperDay
ADO2025.PI6.Helper20250519.LiveSync(logger, args);
else if (args[1] == "Day-Helper-2025-05-21")
ADO2025.PI6.Helper20250521.MatchDirectory(logger, args);
else if (args[1] == "Day-Helper-2025-06-01")
ADO2025.PI6.Helper20250601.EquipmentAutomationFrameworkStatus(logger, args);
else if (args[1] == "Day-Helper-2025-06-02")
ADO2025.PI6.Helper20250602.EquipmentAutomationFrameworkCellInstanceStateImageVerbIf(logger, args);
else if (args[1] == "Day-Helper-2025-06-18")
ADO2025.PI6.Helper20250618.MoveAllButXOfEach(logger, args);
else if (args[1] == "Day-Helper-2025-06-28")
ADO2025.PI6.Helper20250628.LogIsoInformation(logger, args);
else if (args[1] == "Day-Helper-2025-07-01")
ADO2025.PI6.Helper20250701.ProcessDataStandardFormatTo(logger, args);
else if (args[1] == "Day-Helper-2025-07-05")
ADO2025.PI6.Helper20250705.ExportFaces(logger, args);
else
throw new Exception(appSettings.Company);
}

View File

@ -17,7 +17,8 @@
<PackageReference Include="MetadataExtractor" Version="2.8.1" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.1" />
<PackageReference Include="runtime.win-x64.Microsoft.DotNet.ILCompiler" Version="8.0.16" />
<PackageReference Include="runtime.win-x64.Microsoft.DotNet.ILCompiler" Version="8.0.17" />
<PackageReference Include="System.Drawing.Common" Version="8.0.10" />
<PackageReference Include="System.Text.Json" Version="9.0.5" />
<PackageReference Include="TextCopy" Version="6.2.1" />
<PackageReference Include="WindowsShortcutFactory" Version="1.2.0" />

View File

@ -16,8 +16,20 @@ internal static partial class HelperMarkdown
private record Input(string? Destination,
string Source,
string? ReplaceWithTitle,
bool UseProcessStart);
private record Table(ReadOnlyCollection<string> Columns,
int ColumnsLine,
ReadOnlyCollection<ReadOnlyCollection<string>> Rows,
string? Title);
private record Block(int Line,
string? Json,
int RowCount,
ReadOnlyCollection<string>? Rows,
string? Title);
private record Record(string Directory,
string File,
string[] Lines);
@ -30,7 +42,7 @@ internal static partial class HelperMarkdown
string FileNameWithoutExtension,
ReadOnlyDictionary<string, object> FrontMatterYaml,
string H1,
bool IsGitOthersModifiedAndDeletedExcludingStandard,
bool? IsGitOthersModifiedAndDeletedExcludingStandard,
bool IsKanbanIndex,
bool IsKanbanMarkdown,
DateTime LastWriteDateTime,
@ -49,15 +61,27 @@ internal static partial class HelperMarkdown
private record MarkdownFileH1AndRelativePath(MarkdownFile? MarkdownFile, string[]? Lines, string? H1, string? RelativePath);
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
[JsonSerializable(typeof(Dictionary<string, object>))]
internal partial class DictionaryStringAndObjectSourceGenerationContext : JsonSerializerContext
{
}
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
[JsonSerializable(typeof(Dictionary<string, JsonElement>))]
internal partial class DictionaryStringAndJsonElementSourceGenerationContext : JsonSerializerContext
{
}
[GeneratedRegex("([A-Z]+(.))")]
private static partial Regex UpperCase();
[GeneratedRegex("(~~)?(#)([a-zA-Z0-9]{6})(~~)?( )")]
private static partial Regex HtmlColor();
[GeneratedRegex("[\\s!?.,@:;|\\\\/\"'`£$%\\^&*{}[\\]()<>~#+\\-=_¬]+")]
private static partial Regex InvalidCharacter();
private static MarkdownExtra GetMarkdownExtra(MarkdownFileAndLines markdownFileAndLines)
{
MarkdownExtra result;
@ -301,10 +325,10 @@ internal static partial class HelperMarkdown
if (!directoryInfo.Exists || (!string.IsNullOrEmpty(directoryInfo.LinkTarget) && !Directory.Exists(directoryInfo.LinkTarget)))
continue;
collection.AddRange(GetFiles(appSettings, directoryInfo, SearchOption.TopDirectoryOnly));
foreach (FileInfo file in collection)
results.Add(file);
foreach (FileInfo fileInfo in collection)
results.Add(fileInfo);
}
return new(results);
return (from l in results orderby l.FullName select l).ToArray().AsReadOnly();
}
internal static LineNumber GetLineNumbers(FileInfo fileInfo)
@ -525,7 +549,7 @@ internal static partial class HelperMarkdown
h1Check = $"# {h1[2..]}";
if (h1Check.Length == h1.Length && h1Check != h1)
{
if (!markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard)
if (markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard is not null && !markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard.Value)
continue;
lines[markdownFile.LineNumber.H1.Value] = h1Check;
File.WriteAllLines(markdownFile.File, lines);
@ -541,7 +565,7 @@ internal static partial class HelperMarkdown
checkName = Path.Combine(markdownFile.Directory, checkFileName);
if (checkName == markdownFile.File)
continue;
if (!markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard)
if (markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard is not null && !markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard.Value)
continue;
File.Move(markdownFile.File, checkName);
result += 1;
@ -658,6 +682,7 @@ internal static partial class HelperMarkdown
Input result;
string? destination = null;
bool useProcessStart = false;
string? replaceWithTitle = null;
string source = Path.GetFullPath(args[0]);
for (int i = 1; i < args.Count; i++)
{
@ -667,6 +692,8 @@ internal static partial class HelperMarkdown
useProcessStart = args[i + 1] == "true";
else if (args[i][1] == 'd')
destination = Path.GetFullPath(args[i + 1]);
else if (args[i][1] == 't')
replaceWithTitle = args[i + 1];
i++;
}
}
@ -678,11 +705,11 @@ internal static partial class HelperMarkdown
if (!Directory.Exists(destination))
_ = Directory.CreateDirectory(destination);
}
result = new(destination, source, useProcessStart);
result = new(Destination: destination, Source: source, ReplaceWithTitle: replaceWithTitle, UseProcessStart: useProcessStart);
return result;
}
private static ReadOnlyDictionary<string, MarkdownFileAndLines> GetRelativeToCollection(AppSettings appSettings, Input input, ReadOnlyCollection<string> gitOthersModifiedAndDeletedExcludingStandardFiles)
private static ReadOnlyDictionary<string, MarkdownFileAndLines> GetRelativeToCollection(AppSettings appSettings, Input input, ReadOnlyCollection<string>? gitOthersModifiedAndDeletedExcludingStandardFiles)
{
Dictionary<string, MarkdownFileAndLines> results = [];
string h1;
@ -696,17 +723,22 @@ internal static partial class HelperMarkdown
string fileNameWithoutExtension;
ReadOnlyCollection<string> lines;
ReadOnlyDictionary<string, object> frontMatterYaml;
bool isGitOthersModifiedAndDeletedExcludingStandard;
bool? isGitOthersModifiedAndDeletedExcludingStandard;
ReadOnlyCollection<FileInfo> files = GetFiles(appSettings, input);
foreach (FileInfo fileInfo in files)
{ // cSpell:disable
if (fileInfo.DirectoryName is null)
continue;
key = Path.GetRelativePath(input.Source, fileInfo.FullName);
isWithinSource = fileInfo.FullName.Contains(input.Source);
isGitOthersModifiedAndDeletedExcludingStandard = gitOthersModifiedAndDeletedExcludingStandardFiles.Contains(fileInfo.FullName);
if (!isWithinSource && results.ContainsKey(key))
continue;
if (gitOthersModifiedAndDeletedExcludingStandardFiles is null)
isGitOthersModifiedAndDeletedExcludingStandard = null;
else
{
isWithinSource = fileInfo.FullName.Contains(input.Source);
isGitOthersModifiedAndDeletedExcludingStandard = gitOthersModifiedAndDeletedExcludingStandardFiles.Contains(fileInfo.FullName);
if (!isWithinSource && results.ContainsKey(key))
continue;
}
lineNumber = GetLineNumbers(fileInfo);
lines = lineNumber.Lines;
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileInfo.FullName);
@ -716,7 +748,7 @@ internal static partial class HelperMarkdown
(type, h1) = GetTypeAndH1(appSettings, h1, lines, lineNumber);
else
{
if (!isGitOthersModifiedAndDeletedExcludingStandard)
if (isGitOthersModifiedAndDeletedExcludingStandard is not null && !isGitOthersModifiedAndDeletedExcludingStandard.Value)
continue;
type = appSettings.DefaultNoteType;
File.WriteAllLines(fileInfo.FullName, ["---", $"type: {type}\"", "---", string.Empty, $"# {h1}"]);
@ -724,20 +756,20 @@ internal static partial class HelperMarkdown
}
isKanbanMarkdown = fileInfo.Name.EndsWith(".knb.md");
isKanbanIndex = fileNameWithoutExtension == "index" && type.StartsWith("kanb", StringComparison.OrdinalIgnoreCase);
markdownFile = new(fileInfo.CreationTime,
fileInfo.DirectoryName,
fileInfo.Extension,
fileInfo.FullName,
fileInfo.Name,
fileNameWithoutExtension,
frontMatterYaml,
h1,
isGitOthersModifiedAndDeletedExcludingStandard,
isKanbanIndex,
isKanbanMarkdown,
fileInfo.LastWriteTime,
lineNumber,
type);
markdownFile = new(CreationDateTime: fileInfo.CreationTime,
Directory: fileInfo.DirectoryName,
Extension: fileInfo.Extension,
File: fileInfo.FullName,
FileName: fileInfo.Name,
FileNameWithoutExtension: fileNameWithoutExtension,
FrontMatterYaml: frontMatterYaml,
H1: h1,
IsGitOthersModifiedAndDeletedExcludingStandard: isGitOthersModifiedAndDeletedExcludingStandard,
IsKanbanIndex: isKanbanIndex,
IsKanbanMarkdown: isKanbanMarkdown,
LastWriteDateTime: fileInfo.LastWriteTime,
LineNumber: lineNumber,
Type: type);
results.Add(key, new(markdownFile, lines.ToArray()));
} // cSpell:restore
return new(results);
@ -763,7 +795,7 @@ internal static partial class HelperMarkdown
markdownFile = relativeTo.Value.MarkdownFile;
if (markdownFile.IsKanbanMarkdown)
continue;
if (!markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard)
if (markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard is not null && !markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard.Value)
continue;
if (markdownFile.LineNumber.FrontMatterYamlEnd is null)
continue;
@ -797,7 +829,7 @@ internal static partial class HelperMarkdown
circularReference = false;
lines = relativeTo.Value.Lines;
markdownFile = relativeTo.Value.MarkdownFile;
if (!markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard)
if (markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard is not null && !markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard.Value)
continue;
for (int i = 0; i < lines.Length; i++)
{
@ -859,7 +891,7 @@ internal static partial class HelperMarkdown
found = false;
lines = relativeTo.Value.Lines;
markdownFile = relativeTo.Value.MarkdownFile;
if (!markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard)
if (markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard is not null && !markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard.Value)
continue;
for (int i = 0; i < lines.Length; i++)
{
@ -912,7 +944,7 @@ internal static partial class HelperMarkdown
write = false;
lines = relativeTo.Value.Lines;
markdownFile = relativeTo.Value.MarkdownFile;
if (!input.UseProcessStart && !markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard)
if (!input.UseProcessStart && markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard is not null && !markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard.Value)
continue;
for (int i = 0; i < lines.Length; i++)
{
@ -940,7 +972,7 @@ internal static partial class HelperMarkdown
}
if (!write)
continue;
if (!markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard)
if (markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard is not null && !markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard.Value)
continue;
File.WriteAllLines(markdownFile.File, lines);
result += 1;
@ -975,7 +1007,7 @@ internal static partial class HelperMarkdown
markdownFile = relativeTo.Value.MarkdownFile;
if (markdownFile.IsKanbanIndex)
continue;
if (!input.UseProcessStart && !markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard)
if (!input.UseProcessStart && markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard is not null && !markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard.Value)
continue;
if (!File.Exists(markdownFile.File))
continue;
@ -1040,7 +1072,7 @@ internal static partial class HelperMarkdown
}
if (!write)
continue;
if (!markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard)
if (markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard is not null && !markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard.Value)
continue;
File.WriteAllLines(markdownFile.File, lines);
result += 1;
@ -1057,18 +1089,12 @@ internal static partial class HelperMarkdown
MarkdownFileAndLines? markdownFileAndLines = GetKanbanIndexMarkdownFileAndLines(relativeToCollection);
if (markdownFileAndLines is not null && File.Exists(markdownFileAndLines.MarkdownFile.File))
{
ReadOnlyDictionary<string, List<Card>> columnsToCards;
ReadOnlyDictionary<string, List<Card>> columnsToCards = GetColumnsToCards(input, relativeToCollection, markdownFileAndLines);
string jsonFile = Path.Combine(input.Destination, $"{nameof(columnsToCards)}.json");
if (File.Exists(jsonFile))
File.Delete(jsonFile);
columnsToCards = GetColumnsToCards(input, relativeToCollection, markdownFileAndLines);
if (columnsToCards.Count == 0)
File.WriteAllText(jsonFile, "{}");
else
{
string json = JsonSerializer.Serialize(columnsToCards, ColumnsAndCardsSourceGenerationContext.Default.ReadOnlyDictionaryStringListCard);
string old = !File.Exists(jsonFile) ? string.Empty : File.ReadAllText(jsonFile);
string json = columnsToCards.Count == 0 ? "{}" : JsonSerializer.Serialize(columnsToCards, ColumnsAndCardsSourceGenerationContext.Default.ReadOnlyDictionaryStringListCard);
if (json != old)
File.WriteAllText(jsonFile, json);
}
}
}
@ -1122,7 +1148,7 @@ internal static partial class HelperMarkdown
results.Insert(0, string.Empty);
}
results.Insert(0, "---");
if (markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard)
if (markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard is not null && markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard.Value)
{
results.Insert(0, updatedLine);
results.Insert(0, createdLine);
@ -1140,7 +1166,7 @@ internal static partial class HelperMarkdown
}
if (markdownFile.LineNumber.Type is null)
results.Insert(markdownFile.LineNumber.FrontMatterYamlEnd.Value, typeLine);
if (markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard)
if (markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard is not null && markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard.Value)
{
if (markdownFile.LineNumber.Updated is null)
results.Insert(markdownFile.LineNumber.FrontMatterYamlEnd.Value, updatedLine);
@ -1176,7 +1202,7 @@ internal static partial class HelperMarkdown
}
if (results.Count == lines.Length && string.Join('\r', lines) == string.Join('\r', results))
continue;
if (!markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard)
if (markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard is not null && !markdownFile.IsGitOthersModifiedAndDeletedExcludingStandard.Value)
continue;
File.WriteAllLines(markdownFile.File, results);
File.SetLastWriteTime(markdownFile.File, markdownFile.LastWriteDateTime);
@ -1235,7 +1261,351 @@ internal static partial class HelperMarkdown
logger.LogInformation("{updated} Markdown file(s) were updated", updated);
}
if (!string.IsNullOrEmpty(input.Destination))
{
SaveColumnToCards(input, relativeToCollection);
SaveTablesToJson(appSettings, logger, input);
}
}
private static void SaveTablesToJson(AppSettings appSettings, ILogger<Worker> logger, Input input)
{
if (string.IsNullOrEmpty(input.Destination))
throw new NotSupportedException();
string old;
string json;
string[] lines;
string fileName;
List<Block> blocks;
string directoryName;
List<string>? jsonLines;
MarkdownFile markdownFile;
List<string> fileNames = [];
ReadOnlyCollection<Table> tables;
Dictionary<string, List<string>> results = [];
ReadOnlyCollection<Block> javaScriptObjectNotationBlocks;
ReadOnlyCollection<Block> yetAnotherMarkupLanguageBlocks;
ReadOnlyDictionary<string, MarkdownFileAndLines> relativeToCollection = GetRelativeToCollection(appSettings, input, gitOthersModifiedAndDeletedExcludingStandardFiles: null);
foreach (KeyValuePair<string, MarkdownFileAndLines> relativeTo in relativeToCollection)
{
if (relativeTo.Value.Lines.Length == 0)
continue;
lines = relativeTo.Value.Lines;
markdownFile = relativeTo.Value.MarkdownFile;
if (markdownFile.IsKanbanIndex)
continue;
if (markdownFile.IsKanbanMarkdown)
continue;
if (markdownFile.FileName.StartsWith("index.yml.md"))
continue;
if (!File.Exists(markdownFile.File))
continue;
tables = GetTables(lines);
javaScriptObjectNotationBlocks = GetJavaScriptObjectNotationBlocks(lines);
yetAnotherMarkupLanguageBlocks = GetYetAnotherMarkupLanguageBlocks(lines);
if (tables.Count == 0 && javaScriptObjectNotationBlocks.Count == 0 && yetAnotherMarkupLanguageBlocks.Count == 0)
continue;
fileName = Path.Combine(input.Destination, $"{markdownFile.FileNameWithoutExtension}.json");
if (fileNames.Contains(fileName))
continue;
fileNames.Add(fileName);
blocks = [];
blocks.AddRange(GetBlocks(tables));
blocks.AddRange(javaScriptObjectNotationBlocks);
blocks.AddRange(GetBlocks(logger, markdownFile, yetAnotherMarkupLanguageBlocks));
if (blocks.Count == 0)
continue;
directoryName = Path.GetFileName(Path.Combine(input.Destination, markdownFile.Directory));
if (!results.TryGetValue(directoryName, out jsonLines))
{
results.Add(directoryName, []);
if (!results.TryGetValue(directoryName, out jsonLines))
throw new Exception();
}
json = GetJson(input, markdownFile, blocks.AsReadOnly());
jsonLines.Add(json);
}
foreach (KeyValuePair<string, List<string>> keyValuePair in results)
{
json = string.Concat('[', Environment.NewLine, string.Join($",{Environment.NewLine}", keyValuePair.Value), Environment.NewLine, ']');
fileName = Path.Combine(input.Destination, $"{keyValuePair.Key}.json");
old = !File.Exists(fileName) ? string.Empty : File.ReadAllText(fileName);
if (json != old)
{
File.WriteAllText(fileName, json);
logger.LogInformation("Updated json file for <{fileName}>", fileName);
}
}
}
private static ReadOnlyCollection<Table> GetTables(string[] lines)
{
List<Table> results = [];
Table table;
string? title;
string[] segments;
int? columnsLine = null;
List<ReadOnlyCollection<string>> rows = [];
string[]? columns = null;
for (int i = 0; i < lines.Length; i++)
{
if (columns is null && (!lines[i].StartsWith('|') || !lines[i].EndsWith('|') || i + 3 >= lines.Length))
continue;
if (columns is null && (lines[i + 1].Length < 3 || lines[i + 1][0] != '|' || (lines[i + 1][1] is not ':' and not '-')))
continue;
if (columns is null)
{
columnsLine = i;
segments = lines[i][1..^1].Split('|');
columns = (from l in segments select l.Trim()).ToArray();
i++;
continue;
}
segments = lines[i].Length < 3 ? [] : lines[i][1..^1].Split('|');
rows.Add((from l in segments select l.Trim()).ToArray().AsReadOnly());
if (columns is not null && columnsLine is not null && string.IsNullOrEmpty(lines[i]))
{
if (columnsLine.Value - 2 > 0 && lines[columnsLine.Value - 2].StartsWith('#'))
title = lines[columnsLine.Value - 2];
else if (columnsLine.Value - 4 > 0 && lines[columnsLine.Value - 4].StartsWith('#'))
title = lines[columnsLine.Value - 4];
else
title = null;
rows.RemoveAt(rows.Count - 1);
table = new(columns.AsReadOnly(), columnsLine.Value, rows.AsReadOnly(), title);
results.Add(table);
columnsLine = null;
columns = null;
rows = [];
}
}
return results.AsReadOnly();
}
private static string GetParamCase(string value)
{
string result;
StringBuilder stringBuilder = new(value);
Match[] matches = UpperCase().Matches(value).ToArray();
for (int i = matches.Length - 1; i > -1; i--)
_ = stringBuilder.Insert(matches[i].Index, '-');
string[] segments = InvalidCharacter().Split(stringBuilder.ToString().ToLower());
result = string.Join('-', segments).Trim('-');
return result;
}
private static ReadOnlyCollection<Block> GetBlocks(ReadOnlyCollection<Table> tables)
{
List<Block> results = [];
Block block;
string json;
foreach (Table table in tables)
{
if (table.Title is null)
continue;
if (table.Rows.Count == 0)
continue;
json = GetJson(table);
block = new(Line: table.ColumnsLine, Json: json, RowCount: table.Rows.Count, Rows: null, Title: table.Title);
results.Add(block);
}
return results.AsReadOnly();
}
private static string GetJson(Table table)
{
string result;
string line;
string value;
string[] segments;
List<string> lines = [];
for (int i = 0; i < table.Rows.Count; i++)
{
line = "{";
segments = table.Rows[i].ToArray();
if (segments.Length != table.Columns.Count)
break;
for (int c = 0; c < segments.Length; c++)
{
value = segments[c].Replace("\\", "\\\\").Replace("\"", "\\\"");
line += string.Concat('"', table.Columns[c].Trim('"'), '"', ':', '"', value, '"', ',');
}
line = string.Concat(line[..^1], '}');
lines.Add(line);
}
result = string.Concat('[', Environment.NewLine, string.Join($",{Environment.NewLine}", lines), Environment.NewLine, ']');
return result;
}
private static ReadOnlyCollection<Block> GetJavaScriptObjectNotationBlocks(string[] lines)
{
List<Block> results = [];
string json;
string? title;
int? blockLine = null;
List<string> rows = [];
Block javaScriptObjectNotationBlock;
for (int i = 0; i < lines.Length; i++)
{
if (blockLine is null && !lines[i].StartsWith("```json"))
continue;
if (blockLine is null)
{
blockLine = i;
continue;
}
rows.Add(lines[i]);
if (blockLine is not null && lines[i] == "```")
{
rows.RemoveAt(rows.Count - 1);
if (blockLine.Value - 2 > 0 && lines[blockLine.Value - 2].StartsWith('#'))
title = lines[blockLine.Value - 2];
else if (blockLine.Value - 4 > 0 && lines[blockLine.Value - 4].StartsWith('#'))
title = lines[blockLine.Value - 4];
else
title = null;
if (string.IsNullOrEmpty(title))
continue;
json = string.Join(Environment.NewLine, rows);
javaScriptObjectNotationBlock = new(Line: blockLine.Value, Json: json, RowCount: rows.Count, Rows: null, Title: title);
results.Add(javaScriptObjectNotationBlock);
blockLine = null;
rows = [];
}
}
return results.AsReadOnly();
}
private static ReadOnlyCollection<Block> GetYetAnotherMarkupLanguageBlocks(string[] lines)
{
List<Block> results = [];
string? title = null;
int? blockLine = null;
List<string> rows = [];
Block yetAnotherMarkupLanguageBlock;
if (lines[0] == "---")
{
for (int i = 1; i < lines.Length; i++)
{
rows.Add(lines[i]);
if (lines[i] == "---")
{
rows.RemoveAt(rows.Count - 1);
yetAnotherMarkupLanguageBlock = new(Line: 0, Json: null, RowCount: rows.Count, Rows: rows.AsReadOnly(), Title: title);
results.Add(yetAnotherMarkupLanguageBlock);
rows = [];
}
}
}
rows = [];
for (int i = 0; i < lines.Length; i++)
{
if (blockLine is null && !lines[i].StartsWith("```yml") && !lines[i].StartsWith("```yaml"))
continue;
if (blockLine is null)
{
blockLine = i;
continue;
}
rows.Add(lines[i]);
if (blockLine is not null && lines[i] == "```")
{
rows.RemoveAt(rows.Count - 1);
if (blockLine.Value - 2 > 0 && lines[blockLine.Value - 2].StartsWith('#'))
title = lines[blockLine.Value - 2];
else if (blockLine.Value - 4 > 0 && lines[blockLine.Value - 4].StartsWith('#'))
title = lines[blockLine.Value - 4];
else
title = null;
yetAnotherMarkupLanguageBlock = new(Line: blockLine.Value, Json: null, RowCount: rows.Count, Rows: rows.AsReadOnly(), Title: title);
results.Add(yetAnotherMarkupLanguageBlock);
blockLine = null;
rows = [];
}
}
return results.AsReadOnly();
}
private static ReadOnlyCollection<Block> GetBlocks(ILogger<Worker> logger, MarkdownFile markdownFile, ReadOnlyCollection<Block> yetAnotherMarkupLanguageBlocks)
{
List<Block> results = [];
string key;
Block block;
string json;
string text;
Dictionary<string, object>? keyValuePairs;
Dictionary<string, object> keyValuePairsB = [];
#pragma warning disable IL3050
IDeserializer deserializer = new DeserializerBuilder().Build();
#pragma warning restore IL3050
foreach (Block yaml in yetAnotherMarkupLanguageBlocks)
{
if (yaml.Rows is null || yaml.RowCount == 0)
continue;
if (yaml.Title is null && yaml.Line != 0)
continue;
text = string.Join(Environment.NewLine, yaml.Rows);
try
{ keyValuePairs = deserializer.Deserialize<Dictionary<string, object>>(text); }
catch (Exception)
{
keyValuePairs = null;
logger.LogWarning("Invalid yaml file for <{file}>", markdownFile.FileName);
}
if (keyValuePairs is null)
continue;
keyValuePairsB.Clear();
foreach (KeyValuePair<string, object> keyValuePair in keyValuePairs)
{
key = GetParamCase(keyValuePair.Key);
if (keyValuePairsB.ContainsKey(key))
continue;
if (keyValuePair.Value is IDictionary<object, object>)
{
logger.LogWarning("yaml contains a dictionary not allowed in AOT <{file}>", markdownFile.FileName);
break;
}
else if (keyValuePair.Value is not ICollection<object> collection)
keyValuePairsB.Add(key, keyValuePair.Value);
else
keyValuePairsB.Add(key, string.Join(',', collection));
}
try
{ json = JsonSerializer.Serialize(keyValuePairsB, DictionaryStringAndObjectSourceGenerationContext.Default.DictionaryStringObject); }
catch (Exception)
{
logger.LogWarning("yaml contains special values not allowed in AOT <{file}>", markdownFile.FileName);
continue;
}
block = new(Line: yaml.Line, Json: json, RowCount: yaml.Rows.Count, Rows: null, Title: yaml.Title);
results.Add(block);
}
return results.AsReadOnly();
}
private static string GetJson(Input input, MarkdownFile markdownFile, ReadOnlyCollection<Block> blocks)
{
string result;
string paramCase;
List<string> lines = [];
string fileNameParamCase = GetParamCase(markdownFile.FileNameWithoutExtension);
foreach (Block block in blocks.OrderBy(l => l.Line))
{
paramCase = block.Title is null ? $"Line-{block.Line}" : GetParamCase(block.Title);
if (!string.IsNullOrEmpty(input.ReplaceWithTitle) && paramCase == input.ReplaceWithTitle)
paramCase = $"{fileNameParamCase}-{block.Line}";
lines.Add($"\"{paramCase}\": {block.Json}");
}
result = string.Concat('{',
Environment.NewLine,
$"\"{fileNameParamCase}\": ",
'{',
Environment.NewLine,
string.Join($",{Environment.NewLine}", lines),
Environment.NewLine,
'}',
Environment.NewLine,
'}');
return result;
}
}

7
Scripts/markdown.js Normal file
View File

@ -0,0 +1,7 @@
// import data from './oi-metrology-viewer-0-Line-yaml.json' with { type: 'json' };
// import data from '../.vscode/oi-metrology-viewer-0-Line-yaml.json' with { type: 'json' };
import data from '../.vscode/.helper/hosts-legend-table.json' with { type: 'json' };
data.forEach(element => {
console.log(element.Concat);
});