Compare commits
9 Commits
404ffe18f5
...
07-09-a
Author | SHA1 | Date | |
---|---|---|---|
342af4a210 | |||
89bb87bd14 | |||
e7c1fd2221 | |||
fc4449f515 | |||
6ce6c28db1 | |||
2e4aa313fa | |||
116d5e9734 | |||
5ca22b3792 | |||
b98d1e480b |
1
.gitignore
vendored
1
.gitignore
vendored
@ -336,3 +336,4 @@ ASALocalRun/
|
||||
.extensions-vscode-oss
|
||||
.extensions-vscode-insiders
|
||||
.vscode/.UserSecrets/secrets.json
|
||||
.vscode/.helper
|
||||
|
76
.vscode/launch.json
vendored
76
.vscode/launch.json
vendored
@ -11,6 +11,62 @@
|
||||
"preLaunchTask": "build",
|
||||
"program": "${workspaceFolder}/bin/Debug/net8.0/win-x64/File-Folder-Helper.dll",
|
||||
"args": [
|
||||
"s",
|
||||
"X",
|
||||
"D:/ProgramData/EC_Characterization_Si/Dummy/DEP08CEPIEPSILON/PollPath",
|
||||
"Day-Helper-2025-07-01",
|
||||
"*.pdsf",
|
||||
"987654321",
|
||||
"Time",
|
||||
".json",
|
||||
"id12~CenterTemp,id13~CenterSetpt,id15~FrontTemp,id153~PPSTEPNAME,id154~SystemState,id16~FrontSetpt,id172~LVC1Ratio,id173~LVC1Carrier,id176~TotalWaferCount,i-d-1-7-8~TIME,id18~SideTemp,id183~SCRDrive4,id19~SideSetpt,id193~SCRLOAD4,id21~RearTemp,id22~RearSetpt,id221~LeftDefaultRecipe,id222~RightDefaultRecipe,id223~RecipeCompleteMsg,id25~N2H2Setpt,id26~N2H2Flow,id27~HCLSetpt,id28~HCLFlow,id29~HCLHISetpt,id30~HCLHIFlow,id37~NSRCSetpt,id38~NSRCFlow,id39~NDILSetpt,id40~NDILFlow,id41~NINJSetpt,id42~NINJFlow,id57~LVC1Setpt,id58~LVC1Flow,id61~ROTSetpt,id62~ROTSpeed,id78~LL1State,id79~LL1Init,id80~LL1Lotid,id81~LL1WafersIn,id82~LL1WfrCnt,id83~LL2State,id84~LL2Init,id85~LL2Lotid,id86~LL2WafersIn,id87~LL2WfrCnt,id93~ProcessState,vp93~ProcessState,vp154~SystemState,vp78~LL1State,vp83~LL2State,vp176~TotalWaferCount,vp80~LL1Lotid,vp85~LL2Lotid,vp153~PPSTEPNAME,vp221~LeftDefaultRecipe,vp222~RightDefaultRecipe,vp223~RecipeCompleteMsg",
|
||||
"D:/ProgramData/EC_Characterization_Si/Dummy/DEP08CEPIEPSILON/JavaScriptObjectNotation",
|
||||
"D:/ProgramData/EC_Characterization_Si/Dummy/DEP08CEPIEPSILON/Markdown",
|
||||
"D:/ProgramData/EC_Characterization_Si/Dummy/DEP08CEPIEPSILON/KeyValuePairs",
|
||||
"654321",
|
||||
"s",
|
||||
"s",
|
||||
"X",
|
||||
"D:/ProgramData/EC_Characterization_Si/Dummy/DEP08CEPIEPSILON/R55",
|
||||
"Day-Helper-2023-11-30",
|
||||
"yyMMddhhmmssfff",
|
||||
"\"vp154\"",
|
||||
"s",
|
||||
"X",
|
||||
"V:/Tmp/Phares/Pictures/2023 TI2023.6 Fall Samsung",
|
||||
"Day-Helper-2025-07-05",
|
||||
"x-653889110721.jpg~401223300869.jpg",
|
||||
"3648,2736,1~3024,4032,6",
|
||||
"0.341694,0.599963,0.1642,0.279605~0.552357,0.65095,0.195175,0.32383~0.31002,0.42328,0.0379464,0.0459656",
|
||||
"0.259594,0.460161,0.1642,0.279605~0.45477,0.489035,0.195175,0.32383~0.328993,0.446263,0.0379464,0.0459656",
|
||||
"9",
|
||||
"x-825511723~x-444522128~831410304",
|
||||
"X",
|
||||
"F:/0-ISO-A",
|
||||
"Day-Helper-2025-06-28",
|
||||
"*.iso",
|
||||
"F",
|
||||
"s",
|
||||
"X",
|
||||
"D:/5-Other-Small",
|
||||
"Day-Helper-2024-12-17",
|
||||
".job.json",
|
||||
"thumbs.db~sync.ffs_db~verify.json~.html",
|
||||
"D:/0-ISO-A",
|
||||
"D:/5-Other-Small/Proxmox/Snap2HTML/Snap2HTML.exe",
|
||||
"s",
|
||||
"M",
|
||||
"D:/5-Other-Small/Notes/EC-Documentation",
|
||||
"-d",
|
||||
"D:/5-Other-Small/Notes/EC-Documentation/.vscode/helper",
|
||||
"s",
|
||||
"X",
|
||||
"D:/5-Other-Small/Proxmox/DiskInfo",
|
||||
"Day-Helper-2025-06-18",
|
||||
"*.json",
|
||||
"D:/5-Other-Small/Proxmox/Disk-Info-Old",
|
||||
"-2025-",
|
||||
"1",
|
||||
"s",
|
||||
"X",
|
||||
"D:/Tmp",
|
||||
@ -115,6 +171,26 @@
|
||||
"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
34
.vscode/mklink.md
vendored
@ -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"
|
||||
```
|
||||
|
@ -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,14 +52,17 @@ 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 asidePath;
|
||||
string fileName;
|
||||
bool areTheyTheSame;
|
||||
string directoryName;
|
||||
IEnumerable<Record> records;
|
||||
logger.LogInformation(args[0]);
|
||||
logger.LogInformation(args[1]);
|
||||
logger.LogInformation(args[2]);
|
||||
@ -64,19 +70,34 @@ internal static partial class Helper20241217
|
||||
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 = destination.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);
|
||||
for (int i = 1; i < 3; i++)
|
||||
{
|
||||
if (i == 1)
|
||||
{
|
||||
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.Directory);
|
||||
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);
|
||||
@ -86,22 +107,14 @@ internal static partial class Helper20241217
|
||||
WriteAllText(record.Path, json);
|
||||
continue;
|
||||
}
|
||||
directoryName = Path.GetFileName(record.Directory);
|
||||
asidePath = Path.Combine(record.Directory, $"{directoryName}-{DateTime.Now:yyyy-MM-dd-HH-mm-ss-fff}{record.Job.Extension}");
|
||||
path = $"{destinationDriveLetter}{asidePath[1..]}";
|
||||
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, directoryName, path);
|
||||
WritePassedExtension(record, files, record.DirectoryName, path);
|
||||
logger.LogInformation("Wrote <{path}> extension", path);
|
||||
MovePassedExtension(destination, path);
|
||||
logger.LogInformation("Moved <{path}> extension", path);
|
||||
WriteAllText(record.Path, json);
|
||||
Helpers.HelperDeleteEmptyDirectories.DeleteEmptyDirectories(logger, $"{destinationDriveLetter}{record.Directory[1..]}");
|
||||
WriteAllText(record, json, path);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,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
|
||||
@ -180,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 = [];
|
||||
@ -209,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,
|
||||
@ -237,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
|
||||
{
|
||||
@ -246,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
|
||||
{
|
||||
@ -262,7 +301,7 @@ internal static partial class Helper20241217
|
||||
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);
|
||||
logger.LogInformation("<{directory}> file serialized are different {filesTotalLengthNew} != {filesTotalLengthOld}", record.SourceDirectory, filesTotalLengthNew, filesTotalLengthOld);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -286,33 +325,16 @@ internal static partial class Helper20241217
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private static void MovePassedExtension(string destination, string path)
|
||||
{
|
||||
string checkPath = $"{destination}{path[2..]}";
|
||||
string checkDirectory = Path.GetDirectoryName(checkPath) ?? throw new Exception();
|
||||
if (!Directory.Exists(checkDirectory))
|
||||
_ = Directory.CreateDirectory(checkDirectory);
|
||||
if (System.IO.File.Exists(checkPath))
|
||||
throw new NotImplementedException($"<{checkPath}> already exists!");
|
||||
System.IO.File.Move(path, checkPath);
|
||||
}
|
||||
|
||||
private static void WriteISO(Record record, ReadOnlyCollection<File> files, string path, string directoryName)
|
||||
{
|
||||
string checkDirectory = Path.GetDirectoryName(path) ?? 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.AddFile(file.RelativePath, Path.Combine(record.SourceDirectory, file.RelativePath));
|
||||
builder.Build(path);
|
||||
}
|
||||
|
||||
private static void WriteZIP(Record record, ReadOnlyCollection<File> files, string path)
|
||||
{
|
||||
string checkDirectory = Path.GetDirectoryName(path) ?? throw new Exception();
|
||||
if (!Directory.Exists(checkDirectory))
|
||||
_ = Directory.CreateDirectory(checkDirectory);
|
||||
using ZipArchive zip = ZipFile.Open(path, ZipArchiveMode.Create);
|
||||
string directoryEntry;
|
||||
List<string> directoryEntries = [];
|
||||
@ -325,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");
|
||||
}
|
||||
|
||||
}
|
@ -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))
|
||||
|
@ -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';
|
||||
|
89
ADO2025/PI6/Helper-2025-06-18.cs
Normal file
89
ADO2025/PI6/Helper-2025-06-18.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
89
ADO2025/PI6/Helper-2025-06-28.cs
Normal file
89
ADO2025/PI6/Helper-2025-06-28.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
427
ADO2025/PI6/Helper-2025-07-01.cs
Normal file
427
ADO2025/PI6/Helper-2025-07-01.cs
Normal file
@ -0,0 +1,427 @@
|
||||
|
||||
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 {
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonSerializable(typeof(ReadOnlyDictionary<string, ReadOnlyDictionary<string, string>>))]
|
||||
internal partial class ReadOnlyDictionaryStringReadOnlyDictionaryStringStringSourceGenerationContext : 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]);
|
||||
logger.LogInformation(args[7]);
|
||||
string[] segments;
|
||||
string extension = args[5];
|
||||
string timeColumn = args[4];
|
||||
string searchPattern = args[2];
|
||||
int sizeFilter = int.Parse(args[3]);
|
||||
string[] columns = args[6].Split(',');
|
||||
Dictionary<string, string> columnMapping = [];
|
||||
string sourceDirectory = Path.GetFullPath(args[0].Split('~')[0]);
|
||||
string destinationDirectory = Path.GetFullPath(args[7].Split('~')[0]);
|
||||
foreach (string column in columns) {
|
||||
segments = column.Split('~');
|
||||
columnMapping.Add(segments[0], segments[1]);
|
||||
}
|
||||
string[] directories = Directory.GetDirectories(sourceDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||
ProcessDataStandardFormatTo(logger, sourceDirectory, searchPattern, sizeFilter, timeColumn, extension, columnMapping, destinationDirectory, directories);
|
||||
Helpers.HelperDeleteEmptyDirectories.DeleteEmptyDirectories(logger, sourceDirectory);
|
||||
}
|
||||
|
||||
private static void ProcessDataStandardFormatTo(ILogger<Worker> logger, string sourceDirectory, string searchPattern, int sizeFilter, string timeColumn, string extension, Dictionary<string, string> columnMapping, string destinationDirectory, string[] directories) {
|
||||
string text;
|
||||
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 (sizeFilter < 987654321 && 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}{extension}");
|
||||
if (File.Exists(checkFile)) {
|
||||
continue;
|
||||
}
|
||||
if (extension == ".md") {
|
||||
collections = GetMarkdown(logger, timeColumn, columnMapping, file, fileInfo.Name);
|
||||
if (string.IsNullOrEmpty(collections)) {
|
||||
logger.LogWarning("collections is null");
|
||||
continue;
|
||||
}
|
||||
text = collections;
|
||||
} else if (extension == ".pipe.md") {
|
||||
json = GetJavaScriptObjectNotation(logger, file);
|
||||
if (string.IsNullOrEmpty(json)) {
|
||||
logger.LogWarning("json is null");
|
||||
continue;
|
||||
}
|
||||
pipeTable = GetPipeTable(logger, json);
|
||||
if (string.IsNullOrEmpty(pipeTable)) {
|
||||
logger.LogWarning("pipeTable is null");
|
||||
continue;
|
||||
}
|
||||
markdown = $"# {fileInfo.Name}{Environment.NewLine}{Environment.NewLine}{pipeTable}{Environment.NewLine}";
|
||||
text = markdown;
|
||||
} else if (extension == ".json") {
|
||||
json = GetJavaScriptObjectNotation(logger, file);
|
||||
if (string.IsNullOrEmpty(json)) {
|
||||
logger.LogWarning("json is null");
|
||||
continue;
|
||||
}
|
||||
text = json;
|
||||
} else {
|
||||
logger.LogWarning("{extension} is not mapped!", extension);
|
||||
continue;
|
||||
}
|
||||
File.WriteAllText(checkFile, text);
|
||||
File.SetLastWriteTime(checkFile, 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[] lines) {
|
||||
#pragma warning disable CA1845, IDE0057
|
||||
string result;
|
||||
string record;
|
||||
string value;
|
||||
string[] segments;
|
||||
string? json = null;
|
||||
List<string> records = [];
|
||||
ReadOnlyCollection<string>? footerLines = null;
|
||||
string[] columns = lines[columnTitlesLine].Split('\t');
|
||||
for (int i = columnTitlesLine + 1; i < lines.Length; i++) {
|
||||
if (lines[i].StartsWith("NUM_DATA_ROWS")) {
|
||||
footerLines = GetFooterLines(lines, i);
|
||||
break;
|
||||
}
|
||||
record = "{";
|
||||
segments = lines[i].Split('\t');
|
||||
if (segments.Length > columns.Length) {
|
||||
continue;
|
||||
}
|
||||
for (int c = 0; c < segments.Length; c++) {
|
||||
value = segments[c].Replace("\\", "\\\\").Replace("\"", "\\\"");
|
||||
record += string.Concat('"', columns[c].Trim('"'), '"', ':', '"', value, '"', ',');
|
||||
}
|
||||
record = string.Concat(record.Substring(0, record.Length - 1), '}');
|
||||
records.Add(record);
|
||||
}
|
||||
if (footerLines is not null && footerLines.Count > 0) {
|
||||
ReadOnlyDictionary<string, string> footerKeyValuePairs = GetFooterKeyValuePairs(footerLines);
|
||||
ReadOnlyDictionary<string, ReadOnlyDictionary<string, string>> logisticKeyValuePairs = GetLogisticKeyValuePairs(footerLines, footerKeyValuePairs);
|
||||
json = JsonSerializer.Serialize(logisticKeyValuePairs, ReadOnlyDictionaryStringReadOnlyDictionaryStringStringSourceGenerationContext.Default.ReadOnlyDictionaryStringReadOnlyDictionaryStringString);
|
||||
}
|
||||
string footerText = string.IsNullOrEmpty(json) || json == "{}" ? string.Empty : $",{Environment.NewLine}\"PDSF\":{Environment.NewLine}{json}";
|
||||
result = string.Concat(
|
||||
'{',
|
||||
Environment.NewLine,
|
||||
'"',
|
||||
"Count",
|
||||
'"',
|
||||
": ",
|
||||
records.Count,
|
||||
',',
|
||||
Environment.NewLine,
|
||||
'"',
|
||||
"Records",
|
||||
'"',
|
||||
": ",
|
||||
Environment.NewLine,
|
||||
'[',
|
||||
Environment.NewLine,
|
||||
string.Join($",{Environment.NewLine}", records),
|
||||
Environment.NewLine,
|
||||
']',
|
||||
footerText,
|
||||
'}');
|
||||
return result;
|
||||
#pragma warning restore CA1845, IDE0057
|
||||
}
|
||||
|
||||
private static ReadOnlyCollection<string> GetFooterLines(string[] lines, int i) {
|
||||
List<string> results = [];
|
||||
for (int j = i; j < lines.Length; j++) {
|
||||
results.Add(lines[j]);
|
||||
if (lines[j].StartsWith("END_HEADER"))
|
||||
break;
|
||||
}
|
||||
return results.AsReadOnly();
|
||||
}
|
||||
|
||||
private static ReadOnlyDictionary<string, string> GetFooterKeyValuePairs(ReadOnlyCollection<string> footerLines) {
|
||||
Dictionary<string, string> results = [];
|
||||
string[] segments;
|
||||
foreach (string footerLine in footerLines) {
|
||||
segments = footerLine.Split('\t');
|
||||
if (segments.Length != 2 || string.IsNullOrEmpty(segments[1].Trim())) {
|
||||
continue;
|
||||
}
|
||||
if (segments[1].Contains(';')) {
|
||||
continue;
|
||||
} else {
|
||||
results.Add(segments[0], segments[1]);
|
||||
}
|
||||
}
|
||||
return results.AsReadOnly();
|
||||
}
|
||||
|
||||
private static ReadOnlyDictionary<string, ReadOnlyDictionary<string, string>> GetLogisticKeyValuePairs(ReadOnlyCollection<string> footerLines, ReadOnlyDictionary<string, string> footerKeyValuePairs) {
|
||||
Dictionary<string, ReadOnlyDictionary<string, string>> results = [];
|
||||
string[] segments;
|
||||
string[] subSegments;
|
||||
string[] subSubSegments;
|
||||
Dictionary<string, string>? keyValue;
|
||||
results.Add("Footer", footerKeyValuePairs);
|
||||
Dictionary<string, Dictionary<string, string>> keyValuePairs = [];
|
||||
foreach (string footerLine in footerLines) {
|
||||
segments = footerLine.Split('\t');
|
||||
if (segments.Length != 2 || string.IsNullOrEmpty(segments[1].Trim())) {
|
||||
continue;
|
||||
}
|
||||
if (!segments[1].Contains(';') || !segments[1].Contains('=')) {
|
||||
continue;
|
||||
} else {
|
||||
subSegments = segments[1].Split(';');
|
||||
if (subSegments.Length < 1) {
|
||||
continue;
|
||||
}
|
||||
if (!keyValuePairs.TryGetValue(segments[0], out keyValue)) {
|
||||
keyValuePairs.Add(segments[0], []);
|
||||
if (!keyValuePairs.TryGetValue(segments[0], out keyValue)) {
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
foreach (string segment in subSegments) {
|
||||
subSubSegments = segment.Split('=');
|
||||
if (subSubSegments.Length != 2) {
|
||||
continue;
|
||||
}
|
||||
keyValue.Add(subSubSegments[0], subSubSegments[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (KeyValuePair<string, Dictionary<string, string>> keyValuePair in keyValuePairs) {
|
||||
results.Add(keyValuePair.Key, keyValuePair.Value.AsReadOnly());
|
||||
}
|
||||
return results.AsReadOnly();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
112
ADO2025/PI6/Helper-2025-07-05.cs
Normal file
112
ADO2025/PI6/Helper-2025-07-05.cs
Normal 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}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -169,6 +169,14 @@ internal static class HelperDay
|
||||
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);
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ internal static class Helper20231130
|
||||
return result;
|
||||
}
|
||||
|
||||
private static ReadOnlyCollection<string> GetSystemStateValues(List<string> lines, string[] columns, int keyColumnIndex, ReadOnlyDictionary<string, string> systemStates)
|
||||
private static ReadOnlyCollection<string> GetSystemStateValues(List<string> lines, string[] columns, int keyColumnIndex, ReadOnlyDictionary<string, string> systemStateToNames)
|
||||
{
|
||||
List<string> results = [];
|
||||
string[] values;
|
||||
@ -79,7 +79,7 @@ internal static class Helper20231130
|
||||
keyColumnValue = values[keyColumnIndex];
|
||||
if (string.IsNullOrEmpty(keyColumnValue))
|
||||
continue;
|
||||
if (!systemStates.TryGetValue(keyColumnValue, out systemState))
|
||||
if (!systemStateToNames.TryGetValue(keyColumnValue, out systemState))
|
||||
continue;
|
||||
if (results.Contains(systemState))
|
||||
continue;
|
||||
@ -106,7 +106,7 @@ internal static class Helper20231130
|
||||
string missingKeyDirectory = Path.Combine(sourceDirectory, "Missing-Key");
|
||||
if (!Directory.Exists(missingKeyDirectory))
|
||||
_ = Directory.CreateDirectory(missingKeyDirectory);
|
||||
ReadOnlyDictionary<string, string> systemStates = GetSystemStates();
|
||||
ReadOnlyDictionary<string, string> systemStateToNames = GetSystemStates();
|
||||
ReadOnlyCollection<Record> records = GetRecords(sourceDirectory, timestampFormat);
|
||||
foreach (Record record in records)
|
||||
{
|
||||
@ -132,7 +132,7 @@ internal static class Helper20231130
|
||||
continue;
|
||||
}
|
||||
logger.LogInformation("{timestamp} triggered", record.TimeStamp);
|
||||
systemStateValues = GetSystemStateValues(lines, columns, keyColumnIndex.Value, systemStates);
|
||||
systemStateValues = GetSystemStateValues(lines, columns, keyColumnIndex.Value, systemStateToNames);
|
||||
if (systemStateValues.Count == 0)
|
||||
{
|
||||
File.Move(record.File, Path.Combine(sourceDirectory, missingKeyDirectory, record.FileName));
|
||||
@ -142,7 +142,6 @@ internal static class Helper20231130
|
||||
systemState = string.Join('-', systemStateValues);
|
||||
checkFileName = Path.Combine(Path.GetDirectoryName(record.File) ?? throw new Exception(), $"{record.Equipment}-{record.TimeStamp}-{systemState}.pdsf");
|
||||
File.WriteAllLines(checkFileName, lines);
|
||||
File.Delete(record.File);
|
||||
if (DateTime.TryParseExact(record.TimeStamp, timestampFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
|
||||
File.SetLastWriteTime(checkFileName, dateTime);
|
||||
}
|
||||
|
@ -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" />
|
||||
|
@ -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);
|
||||
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,20 +1089,14 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static (string type, string h1) GetTypeAndH1(AppSettings appSettings, string h1, ReadOnlyCollection<string> lines, LineNumber lineNumber)
|
||||
{
|
||||
@ -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
7
Scripts/markdown.js
Normal 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);
|
||||
});
|
Reference in New Issue
Block a user