diff --git a/.vscode/launch.json b/.vscode/launch.json index 3448e46..93521fb 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -19,7 +19,7 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "cwd": "${workspaceFolder}", - "console": "externalTerminal", + "console": "integratedTerminal", "stopAtEntry": false, "requireExactSource": false }, @@ -34,7 +34,7 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "cwd": "${workspaceFolder}", - "console": "externalTerminal", + "console": "integratedTerminal", "stopAtEntry": false, "requireExactSource": false }, @@ -51,7 +51,7 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "cwd": "${workspaceFolder}", - "console": "externalTerminal", + "console": "integratedTerminal", "stopAtEntry": false, "requireExactSource": false }, @@ -68,7 +68,7 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "cwd": "${workspaceFolder}", - "console": "externalTerminal", + "console": "integratedTerminal", "stopAtEntry": false, "requireExactSource": false }, @@ -85,7 +85,7 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "cwd": "${workspaceFolder}", - "console": "externalTerminal", + "console": "integratedTerminal", "stopAtEntry": false, "requireExactSource": false }, @@ -102,7 +102,7 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "cwd": "${workspaceFolder}", - "console": "externalTerminal", + "console": "integratedTerminal", "stopAtEntry": false, "requireExactSource": false }, @@ -187,7 +187,7 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "cwd": "${workspaceFolder}", - "console": "externalTerminal", + "console": "integratedTerminal", "stopAtEntry": false, "requireExactSource": false }, @@ -202,7 +202,24 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "cwd": "${workspaceFolder}", - "console": "externalTerminal", + "console": "integratedTerminal", + "stopAtEntry": false, + "requireExactSource": false + }, + { + "name": "Metadata-Query", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/Metadata-Query/bin/Debug/net7.0/win-x64/Metadata-Query.dll", + "args": [ + "s" + ], + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "cwd": "${workspaceFolder}", + "console": "integratedTerminal", "stopAtEntry": false, "requireExactSource": false }, @@ -219,7 +236,7 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "cwd": "${workspaceFolder}", - "console": "externalTerminal", + "console": "integratedTerminal", "stopAtEntry": false, "requireExactSource": false }, @@ -236,7 +253,7 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "cwd": "${workspaceFolder}", - "console": "externalTerminal", + "console": "integratedTerminal", "stopAtEntry": false, "requireExactSource": false }, @@ -253,7 +270,7 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "cwd": "${workspaceFolder}", - "console": "externalTerminal", + "console": "integratedTerminal", "stopAtEntry": false, "requireExactSource": false }, @@ -270,7 +287,7 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "cwd": "${workspaceFolder}", - "console": "externalTerminal", + "console": "integratedTerminal", "stopAtEntry": false, "requireExactSource": false }, @@ -287,7 +304,7 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "cwd": "${workspaceFolder}", - "console": "externalTerminal", + "console": "integratedTerminal", "stopAtEntry": false, "requireExactSource": false }, @@ -304,7 +321,7 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "cwd": "${workspaceFolder}", - "console": "externalTerminal", + "console": "integratedTerminal", "stopAtEntry": false, "requireExactSource": false }, @@ -321,7 +338,7 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "cwd": "${workspaceFolder}", - "console": "externalTerminal", + "console": "integratedTerminal", "stopAtEntry": false, "requireExactSource": false } diff --git a/Copy-Distinct/CopyDistinct.cs b/Copy-Distinct/CopyDistinct.cs index 7e0ed98..68580f5 100644 --- a/Copy-Distinct/CopyDistinct.cs +++ b/Copy-Distinct/CopyDistinct.cs @@ -69,16 +69,22 @@ public class CopyDistinct moveBack = false; else { + string directory = Path.Combine(_PropertyConfiguration.RootDirectory, _AppSettings.ResultDirectoryKey); if (!anyLenFiles) throw new NotSupportedException("Use Mirror-Length app first!"); if (string.IsNullOrEmpty(_AppSettings.ResultDirectoryKey)) throw new NotSupportedException("Change appsettings!"); - if (!Directory.Exists(Path.Combine(_PropertyConfiguration.RootDirectory, _AppSettings.ResultDirectoryKey))) + if (!Directory.Exists(directory)) moveBack = false; else { - move = false; - moveBack = true; + if (!Directory.GetFiles(directory, "*", SearchOption.AllDirectories).Any()) + moveBack = false; + else + { + move = false; + moveBack = true; + } } } return (move, filesCollection, anyLenFiles, moveBack); diff --git a/Metadata-Query/Metadata-Query.csproj b/Metadata-Query/Metadata-Query.csproj new file mode 100644 index 0000000..b31e8c0 --- /dev/null +++ b/Metadata-Query/Metadata-Query.csproj @@ -0,0 +1,60 @@ + + + enable + 10.0 + enable + Exe + win-x64 + net7.0 + f89b7242-dbb0-4349-b950-657eb8cf87ef + + + Phares.View.by.Distance.Metadata.Query + false + 7.0.101.1 + Mike Phares + Phares + true + snupkg + + + true + true + true + + + Windows + + + OSX + + + Linux + + + + + + + + + + + + + + + + + + + + + + Always + + + Always + + + \ No newline at end of file diff --git a/Metadata-Query/MetadataQuery.cs b/Metadata-Query/MetadataQuery.cs new file mode 100644 index 0000000..7f36eb5 --- /dev/null +++ b/Metadata-Query/MetadataQuery.cs @@ -0,0 +1,158 @@ +using Microsoft.Extensions.Configuration; +using Phares.Shared; +using Serilog; +using ShellProgressBar; +using System.Text; +using System.Text.Json; +using View_by_Distance.Metadata.Query.Models; +using View_by_Distance.Shared.Models.Methods; + +namespace View_by_Distance.Metadata.Query; + +public class MetadataQuery +{ + + private readonly AppSettings _AppSettings; + private readonly string _WorkingDirectory; + private readonly Configuration _Configuration; + private readonly IsEnvironment _IsEnvironment; + private readonly IConfigurationRoot _ConfigurationRoot; + private readonly Property.Models.Configuration _PropertyConfiguration; + + public MetadataQuery(List args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console) + { + if (isSilent) + { } + if (console is null) + { } + _AppSettings = appSettings; + _IsEnvironment = isEnvironment; + long ticks = DateTime.Now.Ticks; + _WorkingDirectory = workingDirectory; + _ConfigurationRoot = configurationRoot; + ILogger? log = Log.ForContext(); + Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot); + Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration); + _PropertyConfiguration = propertyConfiguration; + _Configuration = configuration; + propertyConfiguration.Update(); + log.Information(propertyConfiguration.RootDirectory); + Verify(); + MetadataQueryFilesInDirectories(log, ticks); + } + + private void Verify() + { + if (_AppSettings is null) + { } + if (_IsEnvironment is null) + { } + if (_Configuration is null) + { } + if (_ConfigurationRoot is null) + { } + if (_WorkingDirectory is null) + { } + if (_PropertyConfiguration is null) + { } + } + + private List<(string FileName, string Count, string TagGroup, string TagIdName, string Value)> GetCollection(long ticks) + { + int count; + string json; + string message; + string fileName; + ProgressBar progressBar; + const string fileSearchFilter = "*"; + const string directorySearchFilter = "*"; + Dictionary>>? dictionary; + List<(string FileName, string Count, string TagGroup, string TagIdName, string Value)> collection = new(); + ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; + List filesCollection = Shared.Models.Stateless.Methods.IDirectory.GetFilesCollection(_PropertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter); + foreach (string[] files in filesCollection) + { + if (!files.Any()) + continue; + message = $"{ticks}) Reading files for <{files.FirstOrDefault()}> - {(int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds)} total second(s)"; + progressBar = new(files.Length, message, options); + foreach (string file in files) + { + count = 0; + progressBar.Tick(); + json = File.ReadAllText(file); + fileName = Path.GetFileName(file); + dictionary = JsonSerializer.Deserialize>>>(json); + if (dictionary is null) + continue; + foreach (KeyValuePair>> keyValuePair in dictionary) + { + foreach (KeyValuePair keyValue in keyValuePair.Value) + count++; + } + foreach (KeyValuePair>> keyValuePair in dictionary) + { + foreach (KeyValuePair keyValue in keyValuePair.Value) + collection.Add(new(fileName, count.ToString("000000"), keyValuePair.Key, keyValue.Key, keyValue.Value)); + } + } + progressBar.Dispose(); + } + return collection; + } + + private static Dictionary> GetKeyValuePairs(List<(string FileName, string Count, string TagGroup, string TagIdName, string Value)> matches) + { + string key; + string line; + List? valuePairs; + Dictionary> keyValuePairs = new(); + foreach ((string fileName, string count, string tagGroup, string tagIdName, string value) in matches) + { + key = $"{tagGroup}\t{tagIdName}\t{value.Trim()}"; + line = $"{tagGroup}\t{tagIdName}\t{value.Trim()}\t{count}\t{fileName}"; + if (!keyValuePairs.TryGetValue(key, out valuePairs)) + { + keyValuePairs.Add(key, new()); + if (!keyValuePairs.TryGetValue(key, out valuePairs)) + throw new Exception(); + } + valuePairs.Add(line); + } + return keyValuePairs; + } + + private void MetadataQueryFilesInDirectories(ILogger log, long ticks) + { + List<(string FileName, string Count, string TagGroup, string TagIdName, string Value)> collection = GetCollection(ticks); + log.Information($"Ready to query {collection.Count} entries?"); + IEnumerable<(string FileName, string Count, string TagGroup, string TagIdName, string Value)> enumerable() + { + foreach ((string FileName, string Count, string TagGroup, string TagIdName, string Value) l in collection) + { + if (l.TagIdName.StartsWith("42016\t") && l.Value != "00000000000000000000000000000000") + { + yield return l; + } + } + } + List<(string FileName, string Count, string TagGroup, string TagIdName, string Value)> matches = enumerable().ToList(); + if (matches.Any()) + { + matches.Sort(); + StringBuilder stringBuilder = new(); + Dictionary> keyValuePairs = GetKeyValuePairs(matches); + foreach (KeyValuePair> keyValuePair in keyValuePairs) + { + if (keyValuePair.Value.Count != 2) + continue; + foreach (string line in keyValuePair.Value) + _ = stringBuilder.AppendLine(line); + } + string checkFile = $"D:/Tmp/Phares/{DateTime.Now.Ticks}.tsv"; + string text = stringBuilder.ToString(); + _ = Shared.Models.Stateless.Methods.IPath.WriteAllText(checkFile, text, updateToWhenMatches: null, compareBeforeWrite: true, updateDateWhenMatches: false); + } + } + +} \ No newline at end of file diff --git a/Metadata-Query/Models/AppSettings.cs b/Metadata-Query/Models/AppSettings.cs new file mode 100644 index 0000000..86c3dd3 --- /dev/null +++ b/Metadata-Query/Models/AppSettings.cs @@ -0,0 +1,16 @@ +using System.Text.Json; + +namespace View_by_Distance.Metadata.Query.Models; + +public record AppSettings(string Company, + int MaxDegreeOfParallelism, + string WorkingDirectoryName) +{ + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); + return result; + } + +} \ No newline at end of file diff --git a/Metadata-Query/Models/Binder/AppSettings.cs b/Metadata-Query/Models/Binder/AppSettings.cs new file mode 100644 index 0000000..25603a8 --- /dev/null +++ b/Metadata-Query/Models/Binder/AppSettings.cs @@ -0,0 +1,44 @@ +using Microsoft.Extensions.Configuration; +using System.Text.Json; + +namespace View_by_Distance.Metadata.Query.Models.Binder; + +public class AppSettings +{ + + public string? Company { get; set; } + public int? MaxDegreeOfParallelism { get; set; } + public string? WorkingDirectoryName { get; set; } + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); + return result; + } + + private static Models.AppSettings Get(AppSettings? appSettings) + { + Models.AppSettings result; + if (appSettings?.Company is null) + throw new NullReferenceException(nameof(appSettings.Company)); + if (appSettings?.MaxDegreeOfParallelism is null) + throw new NullReferenceException(nameof(appSettings.MaxDegreeOfParallelism)); + if (appSettings?.WorkingDirectoryName is null) + throw new NullReferenceException(nameof(appSettings.WorkingDirectoryName)); + result = new( + appSettings.Company, + appSettings.MaxDegreeOfParallelism.Value, + appSettings.WorkingDirectoryName + ); + return result; + } + + public static Models.AppSettings Get(IConfigurationRoot configurationRoot) + { + Models.AppSettings result; + AppSettings? appSettings = configurationRoot.Get(); + result = Get(appSettings); + return result; + } + +} \ No newline at end of file diff --git a/Metadata-Query/Models/Binder/Configuration.cs b/Metadata-Query/Models/Binder/Configuration.cs new file mode 100644 index 0000000..5b16fde --- /dev/null +++ b/Metadata-Query/Models/Binder/Configuration.cs @@ -0,0 +1,59 @@ +using Microsoft.Extensions.Configuration; +using Phares.Shared; +using System.ComponentModel.DataAnnotations; +using System.Text.Json; + +namespace View_by_Distance.Metadata.Query.Models.Binder; + +public class Configuration +{ + +#nullable disable + + [Display(Name = "Ignore Extensions"), Required] public string[] IgnoreExtensions { get; set; } + [Display(Name = "Property Configuration"), Required] public Property.Models.Configuration PropertyConfiguration { get; set; } + [Display(Name = "Person Birthday Format"), Required] public string PersonBirthdayFormat { get; set; } + +#nullable restore + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); + return result; + } + + private static Models.Configuration Get(Configuration? configuration) + { + Models.Configuration result; + if (configuration is null) + throw new NullReferenceException(nameof(configuration)); + if (configuration.IgnoreExtensions is null) + throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); + if (configuration.PersonBirthdayFormat is null) + throw new NullReferenceException(nameof(configuration.PersonBirthdayFormat)); + result = new( + configuration.IgnoreExtensions, + configuration.PersonBirthdayFormat, + configuration.PropertyConfiguration); + return result; + } + + public static Models.Configuration Get(IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, Property.Models.Configuration propertyConfiguration) + { + Models.Configuration result; + Configuration? configuration; + if (isEnvironment is null) + configuration = configurationRoot.Get(); + else + { + string environmentName = IsEnvironment.GetEnvironmentName(isEnvironment); + string section = string.Concat(environmentName, ":", nameof(Configuration)); + IConfigurationSection configurationSection = configurationRoot.GetSection(section); + configuration = configurationSection.Get(); + } + result = Get(configuration); + result.SetAndUpdate(propertyConfiguration); + return result; + } + +} \ No newline at end of file diff --git a/Metadata-Query/Models/Configuration.cs b/Metadata-Query/Models/Configuration.cs new file mode 100644 index 0000000..34dc4df --- /dev/null +++ b/Metadata-Query/Models/Configuration.cs @@ -0,0 +1,38 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace View_by_Distance.Metadata.Query.Models; + +public class Configuration +{ + + protected Property.Models.Configuration _PropertyConfiguration; + public string[] IgnoreExtensions { init; get; } + public string PersonBirthdayFormat { init; get; } + + public Property.Models.Configuration PropertyConfiguration => _PropertyConfiguration; + + [JsonConstructor] + public Configuration( + string[] ignoreExtensions, + string personBirthdayFormat, + Property.Models.Configuration propertyConfiguration) + { + IgnoreExtensions = ignoreExtensions; + PersonBirthdayFormat = personBirthdayFormat; + _PropertyConfiguration = propertyConfiguration; + } + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); + return result; + } + + public void SetAndUpdate(Property.Models.Configuration configuration) + { + _PropertyConfiguration = configuration; + _PropertyConfiguration.Update(); + } + +} \ No newline at end of file diff --git a/Metadata-Query/Models/Stateless/SerilogExtensionMethods.cs b/Metadata-Query/Models/Stateless/SerilogExtensionMethods.cs new file mode 100644 index 0000000..984dc7d --- /dev/null +++ b/Metadata-Query/Models/Stateless/SerilogExtensionMethods.cs @@ -0,0 +1,10 @@ +namespace View_by_Distance.Metadata.Query.Models.Stateless; + +public static class SerilogExtensionMethods +{ + + internal static void Warn(this Serilog.ILogger log, string messageTemplate) => log.Warning(messageTemplate); + + internal static void Info(this Serilog.ILogger log, string messageTemplate) => log.Information(messageTemplate); + +} \ No newline at end of file diff --git a/Metadata-Query/Program.cs b/Metadata-Query/Program.cs new file mode 100644 index 0000000..6bd0d54 --- /dev/null +++ b/Metadata-Query/Program.cs @@ -0,0 +1,71 @@ +using Microsoft.Extensions.Configuration; +using Phares.Shared; +using Serilog; +using System.Diagnostics; +using System.Reflection; +using View_by_Distance.Metadata.Query.Models; +using View_by_Distance.Shared.Models.Stateless.Methods; + +namespace View_by_Distance.Metadata.Query; + +public class Program +{ + + public static void Secondary(List args) + { + LoggerConfiguration loggerConfiguration = new(); + Assembly assembly = Assembly.GetExecutingAssembly(); + bool debuggerWasAttachedAtLineZero = Debugger.IsAttached || assembly.Location.Contains(@"\bin\Debug"); + IsEnvironment isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero); + IConfigurationBuilder configurationBuilder = new ConfigurationBuilder() + .AddEnvironmentVariables() + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true) + .AddUserSecrets(); + IConfigurationRoot configurationRoot = configurationBuilder.Build(); + AppSettings appSettings = Models.Binder.AppSettings.Get(configurationRoot); + if (appSettings.MaxDegreeOfParallelism > Environment.ProcessorCount) + throw new Exception("MaxDegreeOfParallelism must be =< Environment.ProcessorCount!"); + if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName)) + throw new Exception("Working directory name must have a value!"); + string workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName); + Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory); + _ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot); + Log.Logger = loggerConfiguration.CreateLogger(); + ILogger log = Log.ForContext(); + int silentIndex = args.IndexOf("s"); + if (silentIndex > -1) + args.RemoveAt(silentIndex); + try + { + if (args is null) + throw new Exception("args is null!"); + Shared.Models.Console console = new(); + _ = new MetadataQuery(args, isEnvironment, configurationRoot, appSettings, workingDirectory, silentIndex > -1, console); + } + catch (Exception ex) + { + log.Fatal(string.Concat(ex.Message, Environment.NewLine, ex.StackTrace)); + } + finally + { + Log.CloseAndFlush(); + } + if (silentIndex > -1) + log.Debug("Done. Bye"); + else + { + log.Debug("Done. Press 'Enter' to end"); + _ = Console.ReadLine(); + } + } + + public static void Main(string[] args) + { + if (args is not null) + Secondary(args.ToList()); + else + Secondary(new List()); + } + +} \ No newline at end of file diff --git a/Metadata-Query/appsettings.Development.json b/Metadata-Query/appsettings.Development.json new file mode 100644 index 0000000..ad9619a --- /dev/null +++ b/Metadata-Query/appsettings.Development.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Log4netProvider": "Debug" + } + }, + "Serilog": { + "MinimumLevel": "Debug" + } +} \ No newline at end of file diff --git a/Metadata-Query/appsettings.json b/Metadata-Query/appsettings.json new file mode 100644 index 0000000..c5f1182 --- /dev/null +++ b/Metadata-Query/appsettings.json @@ -0,0 +1,127 @@ +{ + "Company": "Mike Phares", + "Destination": "L", + "Linux": {}, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Log4netProvider": "Debug", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "MaxDegreeOfParallelism": 6, + "Serilog": { + "Using": [ + "Serilog.Sinks.Console", + "Serilog.Sinks.File" + ], + "MinimumLevel": "Information", + "WriteTo": [ + { + "Name": "Debug", + "Args": { + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}" + } + }, + { + "Name": "Console", + "Args": { + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}" + } + }, + { + "Name": "File", + "Args": { + "path": "%workingDirectory% - Log/log-.txt", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}", + "rollingInterval": "Hour" + } + } + ], + "Enrich": [ + "FromLogContext", + "WithMachineName", + "WithThreadId" + ], + "Properties": { + "Application": "Sample" + } + }, + "WorkingDirectoryName": "PharesApps", + "Windows": { + "Configuration": { + "DateGroup": "dd514b88", + "DiffPropertyDirectory": "", + "FileNameDirectorySeparator": ".Z.", + "ForcePropertyLastWriteTimeToCreationTime": false, + "MaxImagesInDirectoryForTopLevelFirstPass": 10, + "OutputExtension": ".jpg", + "Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]", + "PersonBirthdayFormat": "yyyy-MM-dd_HH", + "PopulatePropertyId": true, + "PropertiesChangedForProperty": false, + "ResultAllInOne": "_ _ _", + "ResultAllInOneSubdirectoryLength": 2, + "ResultCollection": "[]", + "ResultContent": "()", + "ResultSingleton": "{}", + "RootDirectory": "D:/Images", + "WriteBitmapDataBytes": false, + "IgnoreExtensions": [ + ".gif", + ".GIF", + ".nef", + ".NEF", + ".pdf", + ".PDF" + ], + "ValidImageFormatExtensions": [ + ".bmp", + ".BMP", + ".gif", + ".GIF", + ".jpeg", + ".JPEG", + ".jpg", + ".JPG", + ".png", + ".PNG", + ".tiff", + ".TIFF", + ".tif", + ".TIF" + ], + "ValidMetadataExtensions": [ + ".3gp", + ".3GP", + ".avi", + ".AVI", + ".bmp", + ".BMP", + ".gif", + ".GIF", + ".ico", + ".ICO", + ".jpeg", + ".JPEG", + ".jpg", + ".JPG", + ".m4v", + ".M4V", + ".mov", + ".MOV", + ".mp4", + ".MP4", + ".mta", + ".MTA", + ".png", + ".PNG", + ".tiff", + ".TIFF", + ".tif", + ".TIF" + ] + } + } +} \ No newline at end of file diff --git a/Mirror-Length/MirrorLength.cs b/Mirror-Length/MirrorLength.cs index 7a21a6b..cad6380 100644 --- a/Mirror-Length/MirrorLength.cs +++ b/Mirror-Length/MirrorLength.cs @@ -25,6 +25,7 @@ public class MirrorLength { } _AppSettings = appSettings; _IsEnvironment = isEnvironment; + long ticks = DateTime.Now.Ticks; _WorkingDirectory = workingDirectory; _ConfigurationRoot = configurationRoot; ILogger? log = Log.ForContext(); @@ -35,25 +36,23 @@ public class MirrorLength propertyConfiguration.Update(); log.Information(propertyConfiguration.RootDirectory); Verify(); - List lines = MirrorLengthFilesInDirectories(log); - if (!lines.Any()) - File.WriteAllLines($"D:/Tmp/Phares/{DateTime.Now.Ticks}.tsv", lines); + MirrorLengthFilesInDirectories(log, ticks); } private void Verify() { if (_AppSettings is null) - { } + throw new NullReferenceException(nameof(_AppSettings)); if (_IsEnvironment is null) - { } + throw new NullReferenceException(nameof(_IsEnvironment)); if (_Configuration is null) - { } + throw new NullReferenceException(nameof(_Configuration)); if (_ConfigurationRoot is null) - { } + throw new NullReferenceException(nameof(_ConfigurationRoot)); if (_WorkingDirectory is null) - { } + throw new NullReferenceException(nameof(_WorkingDirectory)); if (_PropertyConfiguration is null) - { } + throw new NullReferenceException(nameof(_PropertyConfiguration)); } private static List<(string, string, DateTime, long)[]> GetToDoCollection(ProgressBar progressBar, List filesCollection) @@ -84,10 +83,10 @@ public class MirrorLength private List<(string, string, int)> GetToDoCollectionForMarkDown(string message, string today) { string[] files; - ProgressBar progressBar; string directoryName; - string[] subDirectories; + ProgressBar progressBar; string subDirectoryName; + string[] subDirectories; List<(string, string, int)> results = new(); ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; string[] directories = Directory.GetDirectories(_PropertyConfiguration.RootDirectory, "*", SearchOption.TopDirectoryOnly); @@ -110,7 +109,7 @@ public class MirrorLength return results; } - private void Write(bool inPlaceSave, ProgressBar progressBar, List<(string directory, string file, DateTime lastWriteTime, long length)[]> results) + private void Write(long ticks, bool inPlaceSave, ProgressBar progressBar, List<(string directory, string file, DateTime lastWriteTime, long length)[]> results) { string checkFile; string checkDirectory; @@ -123,7 +122,7 @@ public class MirrorLength firstDirectory = collection.First().Directory; if (string.IsNullOrEmpty(firstDirectory)) continue; - checkDirectory = inPlaceSave ? firstDirectory : $"{_AppSettings.Destination}{firstDirectory[1..]}"; + checkDirectory = inPlaceSave ? firstDirectory : $"{_AppSettings.Destination}:/{ticks}/{firstDirectory[3..]}"; if (!Directory.Exists(checkDirectory)) _ = Directory.CreateDirectory(checkDirectory); else @@ -133,7 +132,7 @@ public class MirrorLength } foreach ((string directory, string _, DateTime _, long _) in collection) { - checkDirectory = inPlaceSave ? directory : $"{_AppSettings.Destination}{directory[1..]}"; + checkDirectory = inPlaceSave ? directory : $"{_AppSettings.Destination}:/{ticks}/{directory[3..]}"; if (directories.Contains(checkDirectory)) continue; directories.Add(checkDirectory); @@ -142,7 +141,7 @@ public class MirrorLength } foreach ((string _, string file, DateTime lastWriteTime, long length) in collection) { - checkFile = inPlaceSave ? $"{file}len" : $"{_AppSettings.Destination}{file[1..]}len"; + checkFile = inPlaceSave ? $"{file}len" : $"{_AppSettings.Destination}:/{ticks}/{file[3..]}len"; if (!Shared.Models.Stateless.Methods.IPath.WriteAllText(checkFile, length.ToString(), updateToWhenMatches: null, compareBeforeWrite: true, updateDateWhenMatches: false)) continue; File.SetLastWriteTime(checkFile, lastWriteTime); @@ -191,9 +190,8 @@ public class MirrorLength } } - private List MirrorLengthFilesInDirectories(ILogger log) + private void MirrorLengthFilesInDirectories(ILogger log, long ticks) { - List results = new(); string message = nameof(MirrorLength); List<(string, string, int)> collectionForMarkDown; bool inPlaceSave = _PropertyConfiguration.RootDirectory.First() == _AppSettings.Destination; @@ -218,10 +216,9 @@ public class MirrorLength progressBar.Dispose(); progressBar = new(filesCollection.Count, message, options); if (collection.Any()) - Write(inPlaceSave, progressBar, collection); + Write(ticks, inPlaceSave, progressBar, collection); progressBar.Dispose(); } - return results; } } \ No newline at end of file diff --git a/Rename/Rename.cs b/Rename/Rename.cs index b220189..6d879ac 100644 --- a/Rename/Rename.cs +++ b/Rename/Rename.cs @@ -316,15 +316,14 @@ public class Rename private List RenameFilesInDirectories(ILogger log) { List results = new(); + string message; bool nefPresent; - ConsoleKey? consoleKey; ProgressBar progressBar; const string fileSearchFilter = "*"; - string message = ") Renaming files"; const string directorySearchFilter = "*"; List distinctDirectories = new(); - List<(FileHolder, string, string)> toDoCollection; - List<(FileHolder, string)> verifiedToDoCollection; + List<(FileHolder, string)> verifiedToDoCollection = new(); + List<(FileHolder, string, string)> toDoCollection = new(); ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; List filesCollection = Shared.Models.Stateless.Methods.IDirectory.GetFilesCollection(_PropertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter); int count = filesCollection.Select(l => l.Length).Sum(); @@ -332,59 +331,65 @@ public class Rename { if (!files.Any()) continue; + // foreach (string file in files) + // { + // if (!file.EndsWith(".del")) + // continue; + // File.Move(file, file[..^4]); + // } + // continue; distinctDirectories.Clear(); - progressBar = new(count, message, options); + message = $") Renaming files for <{files.FirstOrDefault()}>"; + progressBar = new(files.Length, message, options); if (_AppSettings.RenameUndo) - toDoCollection = GetRenameUndoToDoCollection(progressBar, files); + toDoCollection.AddRange(GetRenameUndoToDoCollection(progressBar, files)); else { nefPresent = files.Any(l => l.EndsWith(".NEF")); if (!nefPresent) - toDoCollection = GetToDoCollection(progressBar, files, nefPresent); + toDoCollection.AddRange(GetToDoCollection(progressBar, files, nefPresent)); else - toDoCollection = GetToDoCollection(progressBar, (from l in files where l.EndsWith(".JPG") select l).ToArray(), nefPresent); + toDoCollection.AddRange(GetToDoCollection(progressBar, (from l in files where l.EndsWith(".JPG") select l).ToArray(), nefPresent)); } progressBar.Dispose(); - verifiedToDoCollection = new(); - foreach ((FileHolder fileHolder, string directory, string to) in toDoCollection) - { - if (distinctDirectories.Contains(directory)) - continue; - distinctDirectories.Add(directory); - } - foreach (string distinctDirectory in distinctDirectories) - { - if (!Directory.Exists(distinctDirectory)) - _ = Directory.CreateDirectory(distinctDirectory); - } - foreach ((FileHolder fileHolder, string directory, string to) in toDoCollection) - { - if (File.Exists(to)) - continue; - verifiedToDoCollection.Add(new(fileHolder, to)); - File.WriteAllText($"{to}.id", $"{to}{Environment.NewLine}{fileHolder.FullName}"); - } - if (!verifiedToDoCollection.Any()) + } + foreach ((FileHolder fileHolder, string directory, string to) in toDoCollection) + { + if (distinctDirectories.Contains(directory)) continue; - consoleKey = null; - log.Information($"Ready to Move {verifiedToDoCollection.Count} file(s)?"); - for (int y = 0; y < int.MaxValue; y++) - { - log.Information("Press \"Y\" key to move file(s), \"N\" key to log file(s) or close console to not move files"); - consoleKey = System.Console.ReadKey().Key; - if (consoleKey is ConsoleKey.Y or ConsoleKey.N) - break; - } - log.Information(". . ."); - if (consoleKey is null || consoleKey.Value != ConsoleKey.Y) - log.Information("Nothing moved!"); - else - { - progressBar = new(count, message, options); - results.AddRange(Move(progressBar, verifiedToDoCollection)); - progressBar.Dispose(); - log.Information("Done Moving"); - } + distinctDirectories.Add(directory); + } + foreach (string distinctDirectory in distinctDirectories) + { + if (!Directory.Exists(distinctDirectory)) + _ = Directory.CreateDirectory(distinctDirectory); + } + foreach ((FileHolder fileHolder, string directory, string to) in toDoCollection) + { + if (File.Exists(to)) + continue; + verifiedToDoCollection.Add(new(fileHolder, to)); + File.WriteAllText($"{to}.id", $"{to}{Environment.NewLine}{fileHolder.FullName}"); + } + ConsoleKey? consoleKey = null; + log.Information($"Ready to Move {verifiedToDoCollection.Count} file(s)?"); + for (int y = 0; y < int.MaxValue; y++) + { + log.Information("Press \"Y\" key to move file(s), \"N\" key to log file(s) or close console to not move files"); + consoleKey = System.Console.ReadKey().Key; + if (consoleKey is ConsoleKey.Y or ConsoleKey.N) + break; + } + log.Information(". . ."); + if (consoleKey is null || consoleKey.Value != ConsoleKey.Y) + log.Information("Nothing moved!"); + else + { + message = ") Renaming files"; + progressBar = new(count, message, options); + results.AddRange(Move(progressBar, verifiedToDoCollection)); + progressBar.Dispose(); + log.Information("Done Moving"); } return results; } diff --git a/Shared/Models/Stateless/Methods/XDirectory.cs b/Shared/Models/Stateless/Methods/XDirectory.cs index 507132d..36d93a0 100644 --- a/Shared/Models/Stateless/Methods/XDirectory.cs +++ b/Shared/Models/Stateless/Methods/XDirectory.cs @@ -44,7 +44,7 @@ internal abstract partial class XDirectory catch (UnauthorizedAccessException) { continue; } } - int ceilingAverage = results.Any() ? GetCeilingAverage(results) : 0; + int ceilingAverage = directory[^1] == '_' || !results.Any() ? 0 : GetCeilingAverage(results); results = GetFilesCollection(results, ceilingAverage); return results; } diff --git a/View-by-Distance-MKLink-Console.sln b/View-by-Distance-MKLink-Console.sln index bd33f10..f0d0a1e 100644 --- a/View-by-Distance-MKLink-Console.sln +++ b/View-by-Distance-MKLink-Console.sln @@ -37,6 +37,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Map", "Map\Map.csproj", "{9 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Metadata", "Metadata\Metadata.csproj", "{961D11A0-44C8-48CD-BEEE-A6E6903AE58F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Metadata-Query", "Metadata-Query\Metadata-Query.csproj", "{E77FC150-3D3F-4009-93B3-AEF99393D28E}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mirror-Length", "Mirror-Length\Mirror-Length.csproj", "{035A3DB4-1D0B-4872-ABAE-1D637BB89B1C}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Move-By-Id", "Move-By-Id\Move-By-Id.csproj", "{0FDFBC71-3801-483F-A4AC-CC8CF857D54F}" @@ -212,5 +214,9 @@ Global {BFF75D8C-48E6-4B84-B480-3E5A4F9B2DD8}.Debug|Any CPU.Build.0 = Debug|Any CPU {BFF75D8C-48E6-4B84-B480-3E5A4F9B2DD8}.Release|Any CPU.ActiveCfg = Release|Any CPU {BFF75D8C-48E6-4B84-B480-3E5A4F9B2DD8}.Release|Any CPU.Build.0 = Release|Any CPU + {E77FC150-3D3F-4009-93B3-AEF99393D28E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E77FC150-3D3F-4009-93B3-AEF99393D28E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E77FC150-3D3F-4009-93B3-AEF99393D28E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E77FC150-3D3F-4009-93B3-AEF99393D28E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal