diff --git a/.vscode/launch.json b/.vscode/launch.json index 677e4be..bee5bd9 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -193,6 +193,23 @@ "stopAtEntry": false, "requireExactSource": false }, + { + "name": "Person", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/Person/bin/Debug/net7.0/win-x64/Person.dll", + "args": [ + "s" + ], + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "cwd": "${workspaceFolder}", + "console": "externalTerminal", + "stopAtEntry": false, + "requireExactSource": false + }, { "name": "Rename", "type": "coreclr", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 25f4871..cef7220 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,6 +1,65 @@ { "version": "2.0.0", + "options": { + "env": { + "serverUserSecretsId": "7ca5318a-9332-4217-b9d8-cae696629934" + } + }, "tasks": [ + { + "label": "userSecretsInit", + "command": "dotnet", + "type": "process", + "args": [ + "user-secrets", + "-p", + "${workspaceFolder}/Person/Person.csproj", + "init" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "userSecretsSet", + "command": "dotnet", + "type": "process", + "args": [ + "user-secrets", + "-p", + "${workspaceFolder}/Person/Person.csproj", + "set", + "SaveDirectory", + "D:/1) Images A/Images-9b89679-Results/A2) People/9b89679/([])" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "userSecretsMkLink", + "command": "cmd", + "type": "shell", + "args": [ + "/c", + "mklink", + "/J", + ".vscode\\UserSecrets", + "${userHome}\\AppData\\Roaming\\Microsoft\\UserSecrets\\$env:serverUserSecretsId" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "format", + "command": "dotnet", + "type": "process", + "args": [ + "format", + "--report", + ".vscode", + "--verbosity", + "detailed", + "--severity", + "warn" + ], + "problemMatcher": "$msCompile" + }, { "label": "build", "command": "dotnet", diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index 8f6b8e5..5ce67a8 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -123,10 +123,10 @@ public partial class DlibDotNet if (rootResultsDirectory is null) throw new Exception(); Storage storage = new(rootDirectory, rootResultsDirectory, peopleRootDirectory); - _GEDCOMFile = Path.GetFullPath(string.Concat(peopleRootDirectory, configuration.GEDCOMFile)); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(peopleRootDirectory, "{}")); + _GEDCOMFile = string.IsNullOrEmpty(configuration.GEDCOMFile) ? null : Path.GetFullPath(string.Concat(peopleRootDirectory, configuration.GEDCOMFile)); (_GEDCOMHeaderLines, Dictionary> individuals, _GEDCOMFooterLines) = Shared.Models.Stateless.Methods.IPerson.GetIndividuals(_GEDCOMFile); - _PersonContainers = Shared.Models.Stateless.Methods.IPersonContainer.GetPersonContainers(storage, configuration.PersonBirthdayFormat, configuration.PersonCharacters.ToArray(), _Faces.FileNameExtension, individuals); + _PersonContainers = Shared.Models.Stateless.Methods.IPersonContainer.GetPersonContainers(storage, configuration.MappingDefaultName, configuration.PersonBirthdayFormat, configuration.PersonCharacters.ToArray(), _Faces.FileNameExtension, individuals); } { (ImageCodecInfo imageCodecInfo, EncoderParameters encoderParameters, string filenameExtension) = C_Resize.GetTuple( @@ -808,31 +808,6 @@ public partial class DlibDotNet SaveFaceDistances(ticks, mapLogic, distinctFilteredFaces, mappingCollection, dFacesContentDirectory, d2FacePartsContentDirectory, dFacesCollectionDirectory, idToNormalizedRectangleToMapping); } - private static Container? AreAllSameEndsWith(string argZero, Container[] containers) - { - Container? result = null; - string[] directoryNames = Shared.Models.Stateless.Methods.IPath.GetDirectoryNames(argZero); - if (directoryNames.Length > 2) - { - string directoryName; - string rootDirectoryName = directoryNames[^2]; - if (!Directory.Exists(argZero)) - throw new Exception(); - foreach (Container container in containers) - { - if (container.SourceDirectory == argZero) - result = container; - directoryName = Path.GetFileName(container.SourceDirectory); - if (!directoryName.EndsWith(rootDirectoryName)) - { - result = null; - break; - } - } - } - return result; - } - private string SaveUrlAndGetNewRootDirectory(Container container) { if (_Log is null) @@ -1058,8 +1033,11 @@ public partial class DlibDotNet { int t; Container[] containers; + A_Property propertyLogic; string eDistanceContentDirectory; string? a2PeopleContentDirectory; + string aResultsFullGroupDirectory; + string bResultsFullGroupDirectory; string cResultsFullGroupDirectory; string dResultsFullGroupDirectory; string d2ResultsFullGroupDirectory; @@ -1067,7 +1045,7 @@ public partial class DlibDotNet string fPhotoPrismSingletonDirectory; Dictionary> personKeyToIds; Dictionary> fileNameToCollection; - (string aResultsFullGroupDirectory, string bResultsFullGroupDirectory) = GetResultsFullGroupDirectories(); + (aResultsFullGroupDirectory, bResultsFullGroupDirectory) = GetResultsFullGroupDirectories(); string a2PeopleSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "{}"); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); string message = $") Building Container(s) - {totalSeconds} total second(s)"; @@ -1081,10 +1059,8 @@ public partial class DlibDotNet (t, containers) = Shared.Models.Stateless.Methods.IContainer.GetContainers(_Configuration.PropertyConfiguration, aPropertySingletonDirectory); progressBar.Tick(); } - Container? container = AreAllSameEndsWith(argZero, containers); - A_Property propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, aResultsFullGroupDirectory); - B_Metadata metadata = new(_Configuration.PropertyConfiguration, _Configuration.ForceMetadataLastWriteTimeToCreationTime, _Configuration.PropertiesChangedForMetadata, bResultsFullGroupDirectory); - if (!_ArgZeroIsConfigurationRootDirectory || container is null) + propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, aResultsFullGroupDirectory); + if (containers.Length != 1) { a2PeopleContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "([])"); eDistanceContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(E_Distance), "()"); @@ -1098,7 +1074,7 @@ public partial class DlibDotNet eDistanceContentDirectory = Path.Combine($"{Path.GetPathRoot(argZero)}", "()"); fPhotoPrismContentDirectory = Path.Combine($"{Path.GetPathRoot(argZero)}", "()"); fPhotoPrismSingletonDirectory = Path.Combine($"{Path.GetPathRoot(argZero)}", "{}"); - string? newRootDirectory = SaveUrlAndGetNewRootDirectory(container); + string? newRootDirectory = SaveUrlAndGetNewRootDirectory(containers[0]); for (int i = 1; i < 10; i++) { resultsGroupDirectory = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, string.Empty, create: true); @@ -1106,9 +1082,11 @@ public partial class DlibDotNet } argZero = newRootDirectory; _Configuration.PropertyConfiguration.ChangeRootDirectory(newRootDirectory); + (aResultsFullGroupDirectory, bResultsFullGroupDirectory) = GetResultsFullGroupDirectories(); propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), create: false); propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, aResultsFullGroupDirectory); } + B_Metadata metadata = new(_Configuration.PropertyConfiguration, _Configuration.ForceMetadataLastWriteTimeToCreationTime, _Configuration.PropertiesChangedForMetadata, bResultsFullGroupDirectory); containers = Shared.Models.Stateless.Methods.IContainer.SortContainers(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, _ArgZeroIsConfigurationRootDirectory, argZero, containers); MapLogic mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, _PersonContainers, ticks, a2PeopleSingletonDirectory, eDistanceContentDirectory); personKeyToIds = mapLogic.GetPersonKeyToIds(); @@ -1128,7 +1106,7 @@ public partial class DlibDotNet File.WriteAllText(Path.Combine(eDistanceContentDirectory, $"{ticks}.json"), json); foreach (string outputResolution in _Configuration.OutputResolutions) { - if (_PropertyRootExistedBefore || container is not null) + if (_PropertyRootExistedBefore) break; if (!string.IsNullOrEmpty(a2PeopleContentDirectory) && _Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution)) mapLogic.SaveShortcutsForOutputResolutionsPreMapLogic(eDistanceContentDirectory, personKeyToIds, idToLocationContainers, mappingCollection); diff --git a/Instance/Models/Binder/Configuration.cs b/Instance/Models/Binder/Configuration.cs index bee728a..83b6b5f 100644 --- a/Instance/Models/Binder/Configuration.cs +++ b/Instance/Models/Binder/Configuration.cs @@ -138,8 +138,7 @@ public class Configuration throw new NullReferenceException(nameof(configuration.GEDCOMFile)); if (configuration.IgnoreExtensions is null) throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); - if (configuration.IgnoreRelativePaths is null) - throw new NullReferenceException(nameof(configuration.IgnoreRelativePaths)); + configuration.IgnoreRelativePaths ??= Array.Empty(); configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions ??= Array.Empty(); configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions ??= Array.Empty(); if (configuration.LocationDigits is null) diff --git a/Instance/appsettings.Development.json b/Instance/appsettings.Development.json index a9dbe77..fd9a2b8 100644 --- a/Instance/appsettings.Development.json +++ b/Instance/appsettings.Development.json @@ -20,14 +20,15 @@ "xFocusDirectory": "/Hawaii 2022", "FocusModel": "", "xFocusModel": "NIKON D3400", - "GEDCOMFile": "/([])/638158579618344864/638158579618344864-Export.ged", + "GEDCOMFile": "", + "xGEDCOMFile": "/([])/638158748933377321/638158748933377321-Export-Copy.ged", "PersonCharactersCopyCount": 0, "xPersonCharactersCopyCount": 2, "xRootDirectory": "D:/Tmp/phares/Pictures", "xxRootDirectory": "D:/Tmp/Phares/Compare/Corrupt", "xxxRootDirectory": "D:/2) Images B/Not-Copy-Copy-9b89679", "RootDirectory": "D:/1) Images A/Images-9b89679", - "xxxxxRootDirectory": "D:/1) Images A/Images-9b89679/Facebook/=2022.3 Facebook", + "xxxxxRootDirectory": "D:/1) Images A/Images-9b89679/Facebook/2023.2 Facebook", "SaveSortingWithoutPerson": true, "SkipOlderThanDays": null, "xSkipOlderThanDays": 2200, @@ -98,116 +99,7 @@ "/!/Wax" ], "IgnoreRelativePaths": [ - "3757 W Whitman 2017", - "501 Playful Meadows 2006", - "501 Playful Meadows 2007", - "501 Playful Meadows 2008", - "501 Playful Meadows 2009", - "501 Playful Meadows 2010", - "501 Playful Meadows 2013", - "501 Playful Meadows 2015", - "6309 Evesham 2003", - "6309 Evesham 2004", - "Crystal's Wedding 2003", - "Danny's Wedding 2009", - "Door images 2019", - "Family Pictures 2006", - "Family Pictures 2007", - "Family Pictures 2011", - "Family Pictures 2013", - "GrandPrix 2004", - "Kids School Pictures 2004", - "Kristy 2002", - "Kristy Parents Wedding 2005", - "Logan Ultrasound 2007", - "Mandy's Dogs 2008", - "Motorcycles 2010", - "Motorcycles 2013", - "Motorcycles 2014", - "Phares Slides", - "Portrait Innovations April 2008", - "Portrait Innovations December 2007", - "Portrait Innovations June 2008", - "Portrait Innovations March 2012", - "The guys house 2000", - "Tracy Pictures 2005", - "Tracy Pictures 2006", - "Tracy Pictures 2007", - "Tracy Pictures 2008", - "Tracy Pictures 2009", - "Tracy Pictures 2010", - "Tracy Pictures 2011", - "Tracy Pictures 2012", - "Tracy Pictures 2013 Jan-July", - "Tracy Pictures 2013 July- Dec", - "Tracy Pictures 2014", - "Tracy Pictures 2015", - "Tracy Took The Kids 2006", - "Tracy's Bday 2012", - "Tracy's Wedding 2002", - "Trip to Colorado 10 2002", - "Trip to Colorado June 2002", - "Tub 2002", - "Vericruz 2011", - "zzz 2005.1 Spring Tracy Pictures", - "zzz 2005.2 Summer Tracy Pictures", - "zzz 2005.3 Fall Tracy Pictures", - "zzz 2005.4 Winter Tracy Pictures", - "zzz 2006.1 Spring Tracy Pictures", - "zzz 2007.0 Winter Tracy Pictures", - "zzz 2007.2 Summer Tracy Pictures", - "zzz 2008.2 Summer Tracy Pictures", - "zzz 2009.0 Winter Tracy Pictures", - "zzz 2009.2 Summer Tracy Pictures", - "zzz 2009.3 Fall Tracy Pictures", - "zzz 2009.4 Winter Tracy Pictures", - "zzz 2010.0 Winter Tracy Pictures", - "zzz 2010.1 Spring Tracy Pictures", - "zzz 2010.2 Summer Tracy Pictures", - "zzz 2010.3 Fall Tracy Pictures", - "zzz 2011.0 Winter Tracy Pictures", - "zzz 2011.1 Spring Tracy Pictures", - "zzz 2011.2 Summer Tracy Pictures", - "zzz 2011.3 Fall Tracy Pictures", - "zzz 2011.4 Winter Tracy Pictures", - "zzz 2012.0 Winter Tracy Pictures", - "zzz 2012.1 Spring Tracy Pictures", - "zzz 2012.2 Summer Tracy Pictures", - "zzz 2012.3 Fall Tracy Pictures", - "zzz 2012.4 Winter Tracy Pictures", - "zzz 2013.0 Winter Tracy Pictures", - "zzz 2013.1 Spring Tracy Pictures", - "zzz 2013.2 Summer Tracy Pictures", - "zzz 2013.3 Fall Tracy Pictures", - "zzz 2013.4 Winter Tracy Pictures", - "zzz 2014.0 Winter Tracy Pictures", - "zzz 2014.1 Spring Tracy Pictures", - "zzz 2014.2 Summer Tracy Pictures", - "zzz 2014.3 Fall Tracy Pictures", - "zzz 2014.4 Winter Tracy Pictures", - "zzz 2015.0 Winter Tracy Pictures", - "zzz Family Pictures", - "zzz Family Pictures", - "zzz Family Pictures", - "zzz Family Pictures", - "zzz GrandPrix", - "zzz Motorcycles", - "zzz Motorcycles", - "zzz Motorcycles", - "zzz Parents Yard", - "zzz Phares Family Pictures", - "zzz Phares Slides ####", - "zzz Portrait Innovations April", - "zzz Portrait Innovations Files", - "zzz Portrait Innovations June", - "zzz Portrait Innovations March", - "zzz Rex Memorial ####", - "zzz Scanned Grandma's Quilt ####", - "zzz Scanned Pictures Of Kids ####", - "zzz Scanned Prints ####", - "zzz Slide in Name Order Originals (622) ####", - "zzz Tub", - "zzz Vericruz" + "zzz Phares Slides ####" ], "MixedYearRelativePaths": [ "Edited", diff --git a/Map/Models/MapLogic.cs b/Map/Models/MapLogic.cs index e5cb31c..ec44ebd 100644 --- a/Map/Models/MapLogic.cs +++ b/Map/Models/MapLogic.cs @@ -1127,7 +1127,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic directory = Path.Combine($"{eDistanceContentDirectory}---", "Person Key Shortcuts", personKeyFormatted, directoryName); fileName = Path.Combine(directory, $"{mapping.MappingFromItem.ImageFileHolder.Name}.lnk"); results.Add(new(mapping.MappingFromItem.ImageFileHolder.FullName, directory, mapping.MappingFromItem.MinimumDateTime, fileName, mapping.MappingFromLocation.DeterministicHashCodeKey, MakeAllHidden: false)); - if (mapping.MappingFromPerson.DisplayDirectoryName.Length > 1 && mapping.MappingFromPerson.DisplayDirectoryName[0] == 'Z' && mapping.MappingFromPerson.DisplayDirectoryName[1] == ']') + if (IPerson.IsDefaultName(_Configuration.MappingDefaultName, mapping.MappingFromPerson.DisplayDirectoryName)) continue; directory = Path.Combine($"{eDistanceContentDirectory}---", "Name Shortcuts", mapping.MappingFromPerson.DisplayDirectoryName, directoryName); fileName = Path.Combine(directory, $"{mapping.MappingFromItem.ImageFileHolder.Name}.lnk"); diff --git a/Map/Models/Stateless/MapLogic.cs b/Map/Models/Stateless/MapLogic.cs index 1437e35..9a2853a 100644 --- a/Map/Models/Stateless/MapLogic.cs +++ b/Map/Models/Stateless/MapLogic.cs @@ -29,7 +29,7 @@ internal abstract class MapLogic if (personKeys.Contains(personKey)) continue; personBirthday = IPersonBirthday.GetPersonBirthday(personKey); - person = IPerson.GetPerson(configuration.PersonCharacters.ToArray(), configuration.MappingDefaultName, personKey, personBirthday); + person = IPerson.GetPerson(configuration.MappingDefaultName, configuration.PersonCharacters.ToArray(), configuration.MappingDefaultName, personKey, personBirthday); personContainer = new(approximateYears, person, new PersonBirthday[] { personBirthday }, personDisplayDirectoryAllFiles, configuration.MappingDefaultName, personKey); results.Add(personContainer); } @@ -151,7 +151,7 @@ internal abstract class MapLogic throw new Exception($"Move personKey directories up one from {forceSingleImageHumanized} and delete {forceSingleImageHumanized} directory!"); if (personKeyFormatted.Length != configuration.PersonBirthdayFormat.Length) continue; - if (personDisplayDirectoryNames[^1].Length == 1 || personDisplayDirectoryNames[^1] == configuration.MappingDefaultName || !personKeyFormattedCollection.Contains(personKeyFormatted)) + if (personDisplayDirectoryNames[^1].Length == 1 || IPerson.IsDefaultName(configuration.MappingDefaultName, personDisplayDirectoryNames[^1]) || !personKeyFormattedCollection.Contains(personKeyFormatted)) personFirstInitialDirectory = personNameDirectory; else { @@ -167,6 +167,8 @@ internal abstract class MapLogic continue; } personFirstInitialDirectory = Path.Combine(yearDirectory, personFirstInitial.ToString()); + if (Directory.Exists(personFirstInitialDirectory)) + throw new Exception("Forgot to ..."); Directory.Move(personNameDirectory, personFirstInitialDirectory); files = Directory.GetFiles(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly); } @@ -300,7 +302,7 @@ internal abstract class MapLogic personDisplayDirectory = Path.Combine(personDisplayDirectoryNames); if (!personKeyFormattedToPersonContainer.ContainsKey(personKeyFormatted)) { - personContainer = new(configuration.PersonCharacters.ToArray(), personBirthday, personDisplayDirectoryName); + personContainer = new(configuration.MappingDefaultName, configuration.PersonCharacters.ToArray(), personBirthday, personDisplayDirectoryName); personKeyFormattedToPersonContainer.Add(personKeyFormatted, personContainer); } if (personDisplayDirectoryName.Length != 1 && personDisplayDirectoryName != configuration.MappingDefaultName && !personDisplayDirectoryTo.ContainsKey(personDisplayDirectory)) @@ -356,9 +358,10 @@ internal abstract class MapLogic { int result = 0; int? id; + string checkFile; int? normalizedRectangle; List normalizedRectangles; - string newestPersonKeyFormatted; + string? newestPersonKeyFormatted; string personDisplayDirectoryName; List duplicateMappedFaceFiles = new(); Dictionary> idToNormalizedRectangles = new(); @@ -369,6 +372,14 @@ internal abstract class MapLogic foreach ((string personKeyFormatted, string[] personDisplayDirectoryNames, string mappedFaceFile) in collection) { progressBar.Tick(); + if (!personKeyFormattedToNewestPersonKeyFormatted.TryGetValue(personKeyFormatted, out newestPersonKeyFormatted)) + { + checkFile = $"{mappedFaceFile}.abd"; + if (File.Exists(checkFile)) + continue; + File.Move(mappedFaceFile, checkFile); + continue; + } (id, normalizedRectangle) = IMapping.GetConverted(configuration.FacesFileNameExtension, mappedFaceFile); if (id is null || normalizedRectangle is null) { @@ -380,10 +391,6 @@ internal abstract class MapLogic normalizedRectangles = idToNormalizedRectangles[id.Value]; normalizedRectangles.Add(normalizedRectangle.Value); idToNormalizedRectangles[id.Value].Add(normalizedRectangle.Value); - if (!personKeyFormattedToNewestPersonKeyFormatted.ContainsKey(personKeyFormatted)) - newestPersonKeyFormatted = personKeyFormatted; - else - newestPersonKeyFormatted = personKeyFormattedToNewestPersonKeyFormatted[personKeyFormatted]; personDisplayDirectoryName = personDisplayDirectoryNames[^1]; if (string.IsNullOrEmpty(personDisplayDirectoryName)) continue; @@ -398,32 +405,6 @@ internal abstract class MapLogic return new(result, duplicateMappedFaceFiles.Count); } - private static double GetStandardDeviation(IEnumerable values, double average) - { - double result = 0; - if (!values.Any()) - throw new Exception("Collection must have at least one value!"); - double sum = values.Sum(l => (l - average) * (l - average)); - result = Math.Sqrt(sum / values.Count()); - return result; - } - - private static List GetSumCollection(long[] collection) - { - List results = new(); - long result = 0; - foreach (long item in collection) - { - result += item; - if (result > long.MaxValue) - { - results.Add(result); - result = 0; - } - } - return results; - } - private static List GetNotMappedPersonContainers(Configuration configuration, List personContainers, List personKeys, long[] personKeyCollection) { List results = new(); diff --git a/Move-By-Id/Move-By-Id.csproj b/Move-By-Id/Move-By-Id.csproj index 5f802f0..b34ba0d 100644 --- a/Move-By-Id/Move-By-Id.csproj +++ b/Move-By-Id/Move-By-Id.csproj @@ -3,7 +3,7 @@ enable 10.0 enable - WinExe + Exe win-x64 net7.0 diff --git a/Person/.vscode/launch.json b/Person/.vscode/launch.json new file mode 100644 index 0000000..7c5f5ff --- /dev/null +++ b/Person/.vscode/launch.json @@ -0,0 +1,26 @@ +{ + "version": "0.2.0", + "configurations": [ + { + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "name": ".NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/bin/Debug/net7.0/win-x64/Person.dll", + "args": [], + "cwd": "${workspaceFolder}", + // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console + "console": "internalConsole", + "stopAtEntry": false + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + } + ] +} \ No newline at end of file diff --git a/Person/.vscode/tasks.json b/Person/.vscode/tasks.json new file mode 100644 index 0000000..8417c08 --- /dev/null +++ b/Person/.vscode/tasks.json @@ -0,0 +1,41 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/Person.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/Person.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "--project", + "${workspaceFolder}/Person.csproj" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/Person/Models/AppSettings.cs b/Person/Models/AppSettings.cs new file mode 100644 index 0000000..508b0bf --- /dev/null +++ b/Person/Models/AppSettings.cs @@ -0,0 +1,32 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace View_by_Distance.Person.Models; + +public class AppSettings +{ + + public string Company { init; get; } + public int MaxDegreeOfParallelism { init; get; } + public string SaveDirectory { init; get; } + public string WorkingDirectoryName { init; get; } + + [JsonConstructor] + public AppSettings(string company, + int maxDegreeOfParallelism, + string saveDirectory, + string workingDirectoryName) + { + Company = company; + MaxDegreeOfParallelism = maxDegreeOfParallelism; + SaveDirectory = saveDirectory; + WorkingDirectoryName = 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/Person/Models/Binder/AppSettings.cs b/Person/Models/Binder/AppSettings.cs new file mode 100644 index 0000000..7bedbf1 --- /dev/null +++ b/Person/Models/Binder/AppSettings.cs @@ -0,0 +1,46 @@ +using Microsoft.Extensions.Configuration; +using System.Text.Json; + +namespace View_by_Distance.Person.Models.Binder; + +public class AppSettings +{ + +#nullable disable + + public string Company { get; set; } + public int? MaxDegreeOfParallelism { get; set; } + public string SaveDirectory { get; set; } + public string WorkingDirectoryName { get; set; } + +#nullable restore + + 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?.MaxDegreeOfParallelism is null) + throw new NullReferenceException(nameof(appSettings.MaxDegreeOfParallelism)); + result = new( + appSettings.Company, + appSettings.MaxDegreeOfParallelism.Value, + appSettings.SaveDirectory, + 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/Person/Models/Binder/Configuration.cs b/Person/Models/Binder/Configuration.cs new file mode 100644 index 0000000..6c7404d --- /dev/null +++ b/Person/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.Person.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/Person/Models/Configuration.cs b/Person/Models/Configuration.cs new file mode 100644 index 0000000..e788b71 --- /dev/null +++ b/Person/Models/Configuration.cs @@ -0,0 +1,38 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace View_by_Distance.Person.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/Person/Models/Stateless/SerilogExtensionMethods.cs b/Person/Models/Stateless/SerilogExtensionMethods.cs new file mode 100644 index 0000000..60645e4 --- /dev/null +++ b/Person/Models/Stateless/SerilogExtensionMethods.cs @@ -0,0 +1,10 @@ +namespace View_by_Distance.Person.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/Person/Person.cs b/Person/Person.cs new file mode 100644 index 0000000..3c2b5b8 --- /dev/null +++ b/Person/Person.cs @@ -0,0 +1,232 @@ +using Microsoft.Extensions.Configuration; +using Phares.Shared; +using Serilog; +using System.Text.Json; +using View_by_Distance.Person.Models; +using View_by_Distance.Shared.Models; +using View_by_Distance.Shared.Models.Stateless.Methods; + +namespace View_by_Distance.Person; + +public class Person +{ + + private readonly AppSettings _AppSettings; + private readonly string _WorkingDirectory; + private readonly IsEnvironment _IsEnvironment; + private readonly Configuration _Configuration; + private readonly IConfigurationRoot _ConfigurationRoot; + private readonly Property.Models.Configuration _PropertyConfiguration; + + public Person(List args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, Shared.Models.Methods.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(); + string? comparePathRoot = Path.GetDirectoryName(appSettings.SaveDirectory); + if (comparePathRoot is null || comparePathRoot == propertyConfiguration.RootDirectory) + throw new Exception("Nested isn't allowed!"); + if (!Directory.Exists(appSettings.SaveDirectory)) + _ = Directory.CreateDirectory(appSettings.SaveDirectory); + log.Information(propertyConfiguration.RootDirectory); + Verify(); + Loop(ticks, log); + } + + 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 void Loop(long ticks, ILogger log) + { + int age; + string json; + string code; + string? day; + string alias; + string? line; + string? year; + string? month; + bool deceased; + ConsoleKey sex; + long personKey; + string? lastName; + string middleName; + string? firstName; + DateTime? dateTime; + PersonName personName; + string checkDirectory; + ConsoleKey? consoleKey; + string? approximateYears; + string personKeyFormatted; + string personDisplayDirectory; + log.Information($"Ready to create / update a person? [{ticks}]"); + for (int y = 0; y < int.MaxValue; y++) + { + log.Information("Press \"Y\" key to continue, \"N\" key exit or close console"); + consoleKey = System.Console.ReadKey().Key; + log.Information(". . ."); + if (consoleKey is not ConsoleKey.Y and not ConsoleKey.N) + break; + firstName = null; + for (int f = 0; f < 5; f++) + { + log.Information("Enter persons first name (minimum length of two characters)"); + line = System.Console.ReadLine(); + log.Information(". . ."); + if (string.IsNullOrEmpty(line) || line.Length < 2) + continue; + firstName = line; + break; + } + if (firstName is null) + continue; + lastName = null; + for (int f = 0; f < 5; f++) + { + log.Information("Enter persons last name (minimum length of two characters)"); + line = System.Console.ReadLine(); + log.Information(". . ."); + if (string.IsNullOrEmpty(line) || line.Length < 2) + continue; + lastName = line; + break; + } + if (lastName is null) + continue; + log.Information("Enter persons middle name (press enter if they don't have a middle name)"); + line = System.Console.ReadLine(); + log.Information(". . ."); + middleName = string.IsNullOrEmpty(line) ? string.Empty : line; + log.Information("Enter persons alias (press enter if they don't have a alias)"); + line = System.Console.ReadLine(); + log.Information(". . ."); + alias = string.IsNullOrEmpty(line) ? string.Empty : line; + personName = new(new(firstName), new(middleName), new(lastName), new(alias)); + json = JsonSerializer.Serialize(personName, new JsonSerializerOptions { WriteIndented = true }); + log.Information("Is the person \"M\" (Male), \"F\" (Female) or \"U\" (Unknown)"); + consoleKey = System.Console.ReadKey().Key; + log.Information(". . ."); + if (consoleKey is not ConsoleKey.M and not ConsoleKey.F and not ConsoleKey.U) + continue; + sex = consoleKey.Value; + log.Information("Is the person deceased \"Y\" or \"N\""); + consoleKey = System.Console.ReadKey().Key; + log.Information(". . ."); + if (consoleKey is not ConsoleKey.Y and not ConsoleKey.N) + continue; + deceased = consoleKey == ConsoleKey.Y; + dateTime = null; + approximateYears = null; + for (int f = 0; f < 5; f++) + { + day = null; + year = null; + month = null; + approximateYears = null; + log.Information("Enter persons birthday month (press enter if not known) [MMMM || MMM || MM || M]"); + line = System.Console.ReadLine(); + log.Information(". . ."); + if (!string.IsNullOrEmpty(line)) + month = line; + else + { + log.Information("Enter persons approximate age"); + line = System.Console.ReadLine(); + log.Information(". . ."); + if (string.IsNullOrEmpty(line) || !int.TryParse(line, out _)) + continue; + approximateYears = line; + } + log.Information("Enter persons birthday day (press enter if not known)"); + line = System.Console.ReadLine(); + log.Information(". . ."); + if (!string.IsNullOrEmpty(line)) + day = line; + else + { + log.Information("Enter persons approximate age"); + line = System.Console.ReadLine(); + log.Information(". . ."); + if (string.IsNullOrEmpty(line) || !int.TryParse(line, out _)) + continue; + approximateYears = line; + } + log.Information("Enter persons birthday year (press enter if not known)"); + line = System.Console.ReadLine(); + log.Information(". . ."); + if (!string.IsNullOrEmpty(line)) + year = line; + else + { + log.Information("Enter persons approximate age"); + line = System.Console.ReadLine(); + log.Information(". . ."); + if (string.IsNullOrEmpty(line) || !int.TryParse(line, out _)) + continue; + approximateYears = line; + } + if (month is null || day is null || year is null) + dateTime = null; + else + { + dateTime = IPersonBirthday.GetDate(month, day, year); + if (dateTime is not null) + { + (age, _) = IAge.GetAge(new DateTime(ticks).Ticks, dateTime.Value); + approximateYears = age.ToString(); + } + } + if (approximateYears is null && (dateTime is null || dateTime == DateTime.MinValue)) + continue; + break; + } + if (approximateYears is null) + continue; + personDisplayDirectory = Path.Combine(_AppSettings.SaveDirectory, ticks.ToString(), $"{personName.First.Value} {personName.Last.Value}~{approximateYears}"); + if (!Directory.Exists(personDisplayDirectory)) + _ = Directory.CreateDirectory(personDisplayDirectory); + if (dateTime is null) + personKeyFormatted = "2"; + else + { + personKey = dateTime.Value.Ticks; + if (deceased) + code = sex is ConsoleKey.M ? "05" : sex is ConsoleKey.F ? "04" : sex is ConsoleKey.U ? "02" : throw new NotImplementedException(); + else + code = sex is ConsoleKey.M ? "15" : sex is ConsoleKey.F ? "14" : sex is ConsoleKey.U ? "03" : throw new NotImplementedException(); + personKeyFormatted = $"{IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, personKey)[..^2]}{code}"; + } + checkDirectory = Path.Combine(personDisplayDirectory, personKeyFormatted); + if (!Directory.Exists(checkDirectory)) + _ = Directory.CreateDirectory(checkDirectory); + _ = IPath.WriteAllText(Path.Combine(checkDirectory, $"{personKeyFormatted}.json"), json, updateDateWhenMatches: false, compareBeforeWrite: true); + } + log.Information(". . ."); + } + +} \ No newline at end of file diff --git a/Person/Person.csproj b/Person/Person.csproj new file mode 100644 index 0000000..95d2084 --- /dev/null +++ b/Person/Person.csproj @@ -0,0 +1,59 @@ + + + enable + 10.0 + enable + Exe + win-x64;linux-x64 + net7.0 + 7ca5318a-9332-4217-b9d8-cae696629934 + + + Phares.View.by.Distance.Person + 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/Person/Program.cs b/Person/Program.cs new file mode 100644 index 0000000..1f01815 --- /dev/null +++ b/Person/Program.cs @@ -0,0 +1,70 @@ +using Microsoft.Extensions.Configuration; +using Phares.Shared; +using Serilog; +using System.Diagnostics; +using System.Reflection; +using View_by_Distance.Person.Models; +using View_by_Distance.Shared.Models.Stateless.Methods; + +namespace View_by_Distance.Person; + +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); + 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 Person(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/Person/appsettings.Development.json b/Person/appsettings.Development.json new file mode 100644 index 0000000..99cf120 --- /dev/null +++ b/Person/appsettings.Development.json @@ -0,0 +1,17 @@ +{ + "Logging": { + "LogLevel": { + "Log4netProvider": "Debug" + } + }, + "MaxDegreeOfParallelism": 6, + "Serilog": { + "MinimumLevel": "Debug" + }, + "Windows": { + "Configuration": { + "RootDirectory": "C:/", + "VerifyToSeason": [] + } + } +} \ No newline at end of file diff --git a/Person/appsettings.json b/Person/appsettings.json new file mode 100644 index 0000000..f2acf9e --- /dev/null +++ b/Person/appsettings.json @@ -0,0 +1,120 @@ +{ + "Company": "Mike Phares", + "Linux": {}, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Log4netProvider": "Debug", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "MaxDegreeOfParallelism": 6, + "SaveDirectory": "~/", + "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" + } + }, + "Windows": { + "Configuration": { + "DateGroup": "9b89679", + "DiffPropertyDirectory": "", + "FileNameDirectorySeparator": ".Z.", + "ForcePropertyLastWriteTimeToCreationTime": false, + "MaxImagesInDirectoryForTopLevelFirstPass": 10, + "OutputExtension": ".jpg", + "Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]", + "PersonBirthdayFormat": "yyyy-MM-dd_HH", + "PopulatePropertyId": true, + "PropertiesChangedForProperty": false, + "ResultAllInOne": "_ _ _", + "ResultCollection": "[]", + "ResultContent": "()", + "ResultSingleton": "{}", + "RootDirectory": "C:/Tmp/Phares/Compare/Images-9b89679", + "WriteBitmapDataBytes": false, + "IgnoreExtensions": [ + ".gif", + ".GIF", + ".pdf", + ".PDF" + ], + "ValidImageFormatExtensions": [ + ".bmp", + ".BMP", + ".gif", + ".GIF", + ".jpeg", + ".JPEG", + ".jpg", + ".JPG", + ".png", + ".PNG", + ".tiff", + ".TIFF" + ], + "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" + ] + } + }, + "WorkingDirectoryName": "PharesApps" +} \ No newline at end of file diff --git a/Property/Property.csproj b/Property/Property.csproj index c2eab82..2fccb80 100644 --- a/Property/Property.csproj +++ b/Property/Property.csproj @@ -4,7 +4,7 @@ 10.0 enable library - win-x64 + win-x64;linux-x64 net7.0 diff --git a/Rename/Rename.cs b/Rename/Rename.cs index bf7324d..2d8d3b3 100644 --- a/Rename/Rename.cs +++ b/Rename/Rename.cs @@ -2,6 +2,7 @@ using Phares.Shared; using Serilog; using ShellProgressBar; +using System.Text.Json; using View_by_Distance.Rename.Models; using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models.Methods; @@ -35,7 +36,6 @@ public class Rename Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration); _PropertyConfiguration = propertyConfiguration; _Configuration = configuration; - ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; propertyConfiguration.Update(); string? comparePathRoot = Path.GetDirectoryName(appSettings.ComparePathsFile); if (comparePathRoot is null || comparePathRoot == propertyConfiguration.RootDirectory) @@ -43,7 +43,7 @@ public class Rename log.Information(propertyConfiguration.RootDirectory); Verify(); string json = File.ReadAllText(appSettings.ComparePathsFile); - MatchNginx[]? matchNginxCollection = System.Text.Json.JsonSerializer.Deserialize(json); + MatchNginx[]? matchNginxCollection = JsonSerializer.Deserialize(json); if (matchNginxCollection is null) throw new NullReferenceException(nameof(matchNginxCollection)); if (matchNginxCollection.Length == 0 && matchNginxCollection[0].ConvertedPath.Contains("~~~")) @@ -52,7 +52,7 @@ public class Rename Rename2000(matchNginxCollection); else if (matchNginxCollection.Any()) { - List lines = RenameFilesInDirectories(log, options, matchNginxCollection); + List lines = RenameFilesInDirectories(log, matchNginxCollection); File.WriteAllLines($"D:/Tmp/Phares/{DateTime.Now.Ticks}.tsv", lines); if (comparePathRoot != Path.GetPathRoot(matchNginxCollection[0].ConvertedPath)) _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(comparePathRoot); @@ -71,6 +71,8 @@ public class Rename { } if (_WorkingDirectory is null) { } + if (_PropertyConfiguration is null) + { } } private static void MoveMatches(MatchNginx matchNginx) @@ -384,7 +386,7 @@ public class Rename return results; } - private List RenameFilesInDirectories(ILogger log, ProgressBarOptions options, MatchNginx[] matchNginxCollection) + private List RenameFilesInDirectories(ILogger log, MatchNginx[] matchNginxCollection) { List results = new(); string[] files; @@ -393,6 +395,7 @@ public class Rename List<(FileHolder, string)> toDoCollection; List<(FileHolder, string)> verifiedToDoCollection; List allFiles = GetAllFiles(matchNginxCollection); + ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; for (int i = 1; i < 3; i++) { message = $"{i}) Renaming files"; diff --git a/Rename/Rename.csproj b/Rename/Rename.csproj index 9d95ab5..775ee97 100644 --- a/Rename/Rename.csproj +++ b/Rename/Rename.csproj @@ -3,7 +3,7 @@ enable 10.0 enable - WinExe + Exe win-x64 net7.0 diff --git a/Rename/appsettings.Development.json b/Rename/appsettings.Development.json index 811ad96..91a8073 100644 --- a/Rename/appsettings.Development.json +++ b/Rename/appsettings.Development.json @@ -1,5 +1,5 @@ { - "ComparePathsFile": "C:/Users/mikep/AppData/Local/PharesApps/Drag-Drop-Explorer/2023_06/638111927302288853.json", + "ComparePathsFile": "C:/Users/mikep/AppData/Local/PharesApps/Drag-Drop-Explorer/2023_13/638158781544395303.json", "CopyTo": "", "Logging": { "LogLevel": { diff --git a/Shared/Models/PersonContainer.cs b/Shared/Models/PersonContainer.cs index 5af1a7d..ce0515f 100644 --- a/Shared/Models/PersonContainer.cs +++ b/Shared/Models/PersonContainer.cs @@ -28,8 +28,8 @@ public class PersonContainer : Properties.IPersonContainer FilteredIndividualsLines = filteredIndividualsLines; } - public PersonContainer(char[] personCharacters, PersonBirthday birthday, string displayDirectoryName) : - this(Stateless.Methods.IAge.GetApproximateYears(personCharacters, displayDirectoryName), null, Stateless.Methods.IPerson.GetPerson(personCharacters, displayDirectoryName, birthday.Value.Ticks, birthday), new PersonBirthday[] { birthday }, Array.Empty(), displayDirectoryName, birthday.Value.Ticks, null) + public PersonContainer(string mappingDefaultName, char[] personCharacters, PersonBirthday birthday, string displayDirectoryName) : + this(Stateless.Methods.IAge.GetApproximateYears(personCharacters, displayDirectoryName), null, Stateless.Methods.IPerson.GetPerson(mappingDefaultName, personCharacters, displayDirectoryName, birthday.Value.Ticks, birthday), new PersonBirthday[] { birthday }, Array.Empty(), displayDirectoryName, birthday.Value.Ticks, null) { } public PersonContainer(int? approximateYears, PersonBirthday birthdays, string displayDirectoryName, long key) : diff --git a/Shared/Models/Stateless/Methods/IPerson.cs b/Shared/Models/Stateless/Methods/IPerson.cs index 416acb7..e9952d9 100644 --- a/Shared/Models/Stateless/Methods/IPerson.cs +++ b/Shared/Models/Stateless/Methods/IPerson.cs @@ -5,24 +5,34 @@ public interface IPerson // ... + bool TestStatic_IsDefaultName(string mappingDefaultName, string value) => + IsDefaultName(mappingDefaultName, value); + static bool IsDefaultName(string mappingDefaultName, string value) => + value == mappingDefaultName || (value.Length > 1 && value[0] == 'Z' && value[1] == ']'); + + bool TestStatic_IsDefaultName(string mappingDefaultName, Models.Person person) => + IsDefaultName(mappingDefaultName, person); + static bool IsDefaultName(string mappingDefaultName, Models.Person person) => + IsDefaultName(mappingDefaultName, person.Name.Alias is null ? string.Empty : person.Name.Alias.Value); + string TestStatic_GetFileFullName(Properties.IStorage storage, string personBirthdayFormat, Models.Person person) => GetFileFullName(storage, personBirthdayFormat, person); static string GetFileFullName(Properties.IStorage storage, string personBirthdayFormat, Models.Person person) => IPersonBirthday.GetFileFullName(storage, personBirthdayFormat, person.Birthday); - Models.Person TestStatic_GetPerson(char[] personCharacters, string personDisplayDirectoryName, long personKey, Models.PersonBirthday personBirthday) => - GetPerson(personCharacters, personDisplayDirectoryName, personKey, personBirthday); - static Models.Person GetPerson(char[] personCharacters, string personDisplayDirectoryName, long personKey, Models.PersonBirthday personBirthday) => - Person.GetPerson(Array.Empty(), null, personKey, personBirthday, personDisplayDirectoryName.Split(personCharacters), null); + Models.Person TestStatic_GetPerson(string mappingDefaultName, char[] personCharacters, string personDisplayDirectoryName, long personKey, Models.PersonBirthday personBirthday) => + GetPerson(mappingDefaultName, personCharacters, personDisplayDirectoryName, personKey, personBirthday); + static Models.Person GetPerson(string mappingDefaultName, char[] personCharacters, string personDisplayDirectoryName, long personKey, Models.PersonBirthday personBirthday) => + Person.GetPerson(mappingDefaultName, personCharacters, personDisplayDirectoryName, Array.Empty(), null, personKey, personBirthday, null); - Models.Person TestStatic_GetPerson(string[] personDisplayDirectoryAllFiles, string personKeyFormatted, long personKey, string[] segments, string[]? filteredIndividualsLines) => - GetPerson(personDisplayDirectoryAllFiles, personKeyFormatted, personKey, segments, filteredIndividualsLines); - static Models.Person GetPerson(string[] personDisplayDirectoryAllFiles, string personKeyFormatted, long personKey, string[] segments, string[]? filteredIndividualsLines) => - Person.GetPerson(personDisplayDirectoryAllFiles, personKeyFormatted, personKey, IPersonBirthday.GetPersonBirthday(personKey), segments, filteredIndividualsLines); + Models.Person TestStatic_GetPerson(string mappingDefaultName, char[] personCharacters, string personDisplayDirectoryName, string[] personDisplayDirectoryAllFiles, string personKeyFormatted, long personKey, string[]? filteredIndividualsLines) => + GetPerson(mappingDefaultName, personCharacters, personDisplayDirectoryName, personDisplayDirectoryAllFiles, personKeyFormatted, personKey, filteredIndividualsLines); + static Models.Person GetPerson(string mappingDefaultName, char[] personCharacters, string personDisplayDirectoryName, string[] personDisplayDirectoryAllFiles, string personKeyFormatted, long personKey, string[]? filteredIndividualsLines) => + Person.GetPerson(mappingDefaultName, personCharacters, personDisplayDirectoryName, personDisplayDirectoryAllFiles, personKeyFormatted, personKey, IPersonBirthday.GetPersonBirthday(personKey), filteredIndividualsLines); - (string[] headerLines, Dictionary> individuals, string[] footerLines) TestStatic_GetIndividuals(string gedCOMFile) => + (string[] headerLines, Dictionary> individuals, string[] footerLines) TestStatic_GetIndividuals(string? gedCOMFile) => GetIndividuals(gedCOMFile); - static (string[] headerLines, Dictionary> individuals, string[] footerLines) GetIndividuals(string gedCOMFile) => + static (string[] headerLines, Dictionary> individuals, string[] footerLines) GetIndividuals(string? gedCOMFile) => Person.GetIndividuals(gedCOMFile); string[] TestStatic_GetFiltered(List individualsLines) => diff --git a/Shared/Models/Stateless/Methods/IPersonBirthday.cs b/Shared/Models/Stateless/Methods/IPersonBirthday.cs index 9309875..83d8462 100644 --- a/Shared/Models/Stateless/Methods/IPersonBirthday.cs +++ b/Shared/Models/Stateless/Methods/IPersonBirthday.cs @@ -28,6 +28,11 @@ public interface IPersonBirthday static Models.PersonBirthday GetPersonBirthday(long ticks) => new(new(ticks)); + DateTime? TestStatic_GetDate(string month, string day, string year) => + GetDate(month, day, year); + static DateTime? GetDate(string month, string day, string year) => + PersonBirthday.GetDate(month, day, year); + string TestStatic_GetFileName(string personBirthdayFormat, Models.PersonBirthday personBirthday) => GetFileName(personBirthdayFormat, personBirthday); static string GetFileName(string personBirthdayFormat, Models.PersonBirthday personBirthday) => diff --git a/Shared/Models/Stateless/Methods/IPersonContainer.cs b/Shared/Models/Stateless/Methods/IPersonContainer.cs index 6b0f525..6bf5d95 100644 --- a/Shared/Models/Stateless/Methods/IPersonContainer.cs +++ b/Shared/Models/Stateless/Methods/IPersonContainer.cs @@ -5,10 +5,10 @@ public interface IPersonContainer // ... - Models.PersonContainer[] TestStatic_GetPersonContainers(Properties.IStorage storage, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, Dictionary> individuals) => - GetPersonContainers(storage, personBirthdayFormat, personCharacters, facesFileNameExtension, individuals); - static Models.PersonContainer[] GetPersonContainers(Properties.IStorage storage, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, Dictionary> individuals) => - PersonContainer.GetPersonContainers(storage, personBirthdayFormat, personCharacters, facesFileNameExtension, individuals); + Models.PersonContainer[] TestStatic_GetPersonContainers(Properties.IStorage storage, string mappingDefaultName, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, Dictionary> individuals) => + GetPersonContainers(storage, mappingDefaultName, personBirthdayFormat, personCharacters, facesFileNameExtension, individuals); + static Models.PersonContainer[] GetPersonContainers(Properties.IStorage storage, string mappingDefaultName, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, Dictionary> individuals) => + PersonContainer.GetPersonContainers(storage, mappingDefaultName, personBirthdayFormat, personCharacters, facesFileNameExtension, individuals); List<(long?, string)> TestStatic_GetDisplay(string personBirthdayFormat, Models.PersonContainer personContainer) => GetDisplay(personBirthdayFormat, personContainer); diff --git a/Shared/Models/Stateless/Methods/Person.cs b/Shared/Models/Stateless/Methods/Person.cs index c9a0de4..effad50 100644 --- a/Shared/Models/Stateless/Methods/Person.cs +++ b/Shared/Models/Stateless/Methods/Person.cs @@ -1,3 +1,5 @@ +using System.Text.Json; + namespace View_by_Distance.Shared.Models.Stateless.Methods; internal abstract class Person @@ -49,19 +51,20 @@ internal abstract class Person File.WriteAllLines(exportFile, cleanLines); } - internal static (string[] headerLines, Dictionary> individuals, string[] footerLines) GetIndividuals(string gedCOMFile) + internal static (string[] headerLines, Dictionary> individuals, string[] footerLines) GetIndividuals(string? gedCOMFile) { Dictionary> results = new(); string? nick; int startAt = 0; List lines = new(); + const string startsWith = "0 @"; List headerLines = new(); List footerLines = new(); - string[] sourceLines = File.ReadAllLines(gedCOMFile); + string[] sourceLines = string.IsNullOrEmpty(gedCOMFile) ? Array.Empty() : File.ReadAllLines(gedCOMFile); for (int i = 0; i < sourceLines.Length; i++) { lines.Add(sourceLines[i]); - if (sourceLines[i].EndsWith("@ INDI")) + if (sourceLines[i].StartsWith(startsWith)) { lines.RemoveAt(lines.Count - 1); headerLines.AddRange(lines); @@ -72,41 +75,44 @@ internal abstract class Person } for (int i = startAt; i < sourceLines.Length; i++) { - if (!sourceLines[i].StartsWith("0 @")) + if (!sourceLines[i].StartsWith(startsWith)) continue; nick = null; lines.Add(sourceLines[i]); - for (int j = i + 1; j < sourceLines.Length; j++) + if (sourceLines[i].EndsWith("@ FAM")) { - if (sourceLines[j].StartsWith("0 @I")) - break; - lines.Add(sourceLines[j]); - if (!sourceLines[j].StartsWith("2 NICK ")) - continue; - nick = sourceLines[j][7..]; + for (int j = i + 1; j < sourceLines.Length; j++) + lines.Add(sourceLines[j]); + footerLines.AddRange(lines); + break; } - if (string.IsNullOrEmpty(nick)) + else if (sourceLines[i].EndsWith("@ INDI")) { - if (lines[^1] != "0 TRLR") - throw new Exception(string.Join(Environment.NewLine, lines)); - else + for (int j = i + 1; j < sourceLines.Length; j++) { - footerLines.AddRange(lines); - break; + if (sourceLines[j].StartsWith(startsWith)) + break; + lines.Add(sourceLines[j]); + if (!sourceLines[j].StartsWith("2 NICK ")) + continue; + nick = sourceLines[j][7..]; } + if (string.IsNullOrEmpty(nick)) + throw new Exception(string.Join(Environment.NewLine, lines)); + results.Add(nick, new()); + if (lines.Count > 25) + lines.Clear(); + results[nick].AddRange(lines); + lines.Clear(); } - results.Add(nick, new()); - results[nick].AddRange(lines); - lines.Clear(); + else + throw new NotSupportedException(); } return (headerLines.ToArray(), results, footerLines.ToArray()); } - private static void WriteGedFile(string personKeyFormatted, Models.PersonBirthday personBirthday, string[]? filteredIndividualsLines, Models.PersonName name, string[] matches) + private static void WriteGedComFile(string personKeyFormatted, Models.PersonBirthday personBirthday, string[]? filteredIndividualsLines, Models.PersonName name, bool isDefaultName, string directory) { - string? directory = Path.GetDirectoryName(matches[0]); - if (directory is null) - throw new Exception(); string? sexLine; string? deathLine = null; string jrOrSr; @@ -115,13 +121,13 @@ internal abstract class Person else { if (name.Alias.Value.Contains(" Jr")) - jrOrSr = "Jr"; + jrOrSr = " Jr"; else if (name.Alias.Value.Contains(" Sr")) - jrOrSr = "Sr"; + jrOrSr = " Sr"; else jrOrSr = string.Empty; } - string nameLine = $"1 NAME {name.First.Value}/{name.Last.Value}/{jrOrSr}"; + string nameLine = $"1 NAME {name.First.Value} /{name.Last.Value}/{jrOrSr}"; if (personKeyFormatted[^2..] is "23" or "21" or "19" or "17" or "15") { sexLine = "1 SEX M"; @@ -160,18 +166,18 @@ internal abstract class Person sexLine = "1 SEX U"; else { - string sex; + string code; if (deathLine is null or not "1 DEAT Y") - sex = sexLine[6] is 'M' ? "05" : sexLine[6] is 'F' ? "04" : sexLine[6] is 'U' ? "02" : throw new NotImplementedException(); + code = sexLine[6] is 'M' ? "05" : sexLine[6] is 'F' ? "04" : sexLine[6] is 'U' ? "02" : throw new NotImplementedException(); else - sex = sexLine[6] is 'M' ? "15" : sexLine[6] is 'F' ? "14" : sexLine[6] is 'U' ? "03" : throw new NotImplementedException(); + code = sexLine[6] is 'M' ? "15" : sexLine[6] is 'F' ? "14" : sexLine[6] is 'U' ? "03" : throw new NotImplementedException(); if (directory.EndsWith("00")) - directory = string.Concat(directory[..^2], sex); + directory = string.Concat(directory[..^2], code); else if (directory.EndsWith("01")) - directory = string.Concat(directory[..^2], sex); + directory = string.Concat(directory[..^2], code); else throw new NotImplementedException(); - personKeyFormatted = $"{personKeyFormatted[..^2]}{sex}"; + personKeyFormatted = $"{personKeyFormatted[..^2]}{code}"; } } List pGedLines = new(); @@ -197,6 +203,8 @@ internal abstract class Person pGedLines.Add("1 BIRT"); pGedLines.Add($"2 DATE {personBirthday.Value:dd MMM yyyy}"); } + if (isDefaultName) + pGedLines.Add("9 NOTE"); if (filteredIndividualsLines is not null) { for (int i = 1; i < filteredIndividualsLines.Length; i++) @@ -257,13 +265,11 @@ internal abstract class Person { if (personContainer.Key is null || personContainer.Birthdays is null || personContainer.Person is null || !personContainer.Birthdays.Any()) continue; - if (personContainer.DisplayDirectoryName == mappingDefaultName || personContainer.Person.Name.Alias.Value == "Z") + if (IPerson.IsDefaultName(mappingDefaultName, personContainer.DisplayDirectoryName) || IPerson.IsDefaultName(mappingDefaultName, personContainer.Person)) continue; if (distinct.Contains(personContainer.Key.Value)) continue; distinct.Add(personContainer.Key.Value); - if (!personKeyToIds.ContainsKey(personContainer.Key.Value)) - continue; personBirthday = personContainer.Birthdays[zero]; personKeyFormatted = IPersonBirthday.GetFormatted(personBirthdayFormat, personBirthday); by = IPersonBirthday.IsCounterPersonBirthday(personBirthday) ? resultAllInOne : "People"; @@ -275,6 +281,8 @@ internal abstract class Person continue; pGedLines = File.ReadAllLines(pGedFiles[0]); lines.AddRange(pGedLines); + if (!personKeyToIds.ContainsKey(personContainer.Key.Value)) + lines.Add("1 NOTE"); // segments = personContainer.DisplayDirectoryName.Split(_Configuration.PersonCharacters.ToArray()); // if (segments.Length < 2) // directory = Path.Combine(rootDirectory, $"000 {personKeyFormatted} {personContainer.DisplayDirectoryName}"); @@ -288,9 +296,10 @@ internal abstract class Person File.WriteAllLines(Path.Combine(a2PeopleContentDirectory, $"{ticks}.ged"), lines); } - internal static Models.Person GetPerson(string[] personDisplayDirectoryAllFiles, string? personKeyFormatted, long personKey, Models.PersonBirthday personBirthday, string[] segments, string[]? filteredIndividualsLines) + internal static Models.Person GetPerson(string mappingDefaultName, char[] personCharacters, string personDisplayDirectoryName, string[] personDisplayDirectoryAllFiles, string? personKeyFormatted, long personKey, Models.PersonBirthday personBirthday, string[]? filteredIndividualsLines) { Models.Person result; + string[] matches; const int zero = 0; List urls = new(); Models.PersonId id = new(personKey); @@ -298,10 +307,29 @@ internal abstract class Person List numbers = new(); List comments = new(); List addresses = new(); - Models.PersonName name = PersonName.Create(segments[zero]); - string[] matches = (from l in personDisplayDirectoryAllFiles where !string.IsNullOrEmpty(personKeyFormatted) && l.Contains(personKeyFormatted) select l).ToArray(); + string checkFileName = $"{personDisplayDirectoryName[zero]}.json"; + bool isDefaultName = IPerson.IsDefaultName(mappingDefaultName, personDisplayDirectoryName); + string nameWithoutApproximateYears = !isDefaultName ? personDisplayDirectoryName.Split(personCharacters)[zero] : personDisplayDirectoryName; + matches = (from l in personDisplayDirectoryAllFiles where Path.GetFileName(l) == checkFileName select l).ToArray(); + Models.PersonName? name; + if (!matches.Any()) + name = PersonName.Create(nameWithoutApproximateYears); + else + { + string json = File.ReadAllText(matches[zero]); + name = JsonSerializer.Deserialize(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + name ??= PersonName.Create(nameWithoutApproximateYears); + if (name.Last is null || string.IsNullOrEmpty(name.Last.Value)) + name = PersonName.Create(nameWithoutApproximateYears); + } + matches = (from l in personDisplayDirectoryAllFiles where !string.IsNullOrEmpty(personKeyFormatted) && l.Contains(personKeyFormatted) select l).ToArray(); if (!string.IsNullOrEmpty(personKeyFormatted) && matches.Any()) - WriteGedFile(personKeyFormatted, personBirthday, filteredIndividualsLines, name, matches); + { + string? directory = Path.GetDirectoryName(matches[zero]); + if (directory is null) + throw new Exception(); + WriteGedComFile(personKeyFormatted, personBirthday, filteredIndividualsLines, name, isDefaultName, directory); + } result = new(id, personBirthday, name, comments, urls, numbers, emails, addresses); return result; } diff --git a/Shared/Models/Stateless/Methods/PersonBirthday.cs b/Shared/Models/Stateless/Methods/PersonBirthday.cs index 7161990..a3ccb21 100644 --- a/Shared/Models/Stateless/Methods/PersonBirthday.cs +++ b/Shared/Models/Stateless/Methods/PersonBirthday.cs @@ -132,4 +132,77 @@ internal abstract class PersonBirthday return results; } + private static string? GetMonthShortForm(string month) + { + string? result = month.ToLower()[0] switch + { + // 'j' => "jan", + 'f' => "feb", + // 'm' => "mar", + // 'a' => "apr", + // 'm' => "may", + // 'j' => "jun", + // 'j' => "jul", + // 'a' => "aug", + 's' => "sep", + 'o' => "oct", + 'n' => "nov", + 'd' => "dec", + _ => null + }; + return result; + } + + internal static DateTime? GetDate(string month, string day, string year) + { + DateTime? result; + DateTime dayDateTime; + DateTime yearDateTime; + DateTime monthDateTime; + string? monthShortHand = string.IsNullOrEmpty(month) ? "x" : GetMonthShortForm(month); + if (month.Length > 3) + { + if (!DateTime.TryParseExact($"{month},1,1500", "MMMM,d,yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out monthDateTime)) + monthDateTime = DateTime.MinValue; + } + else if (month.Length == 3) + { + if (!DateTime.TryParseExact($"{month},1,1500", "MMM,d,yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out monthDateTime)) + monthDateTime = DateTime.MinValue; + } + else if (month.Length == 1 && monthShortHand is not null) + { + if (!DateTime.TryParseExact($"{monthShortHand},1,1500", "MMM,d,yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out monthDateTime)) + monthDateTime = DateTime.MinValue; + } + else if (int.TryParse(month, out int _)) + { + if (!DateTime.TryParseExact($"{month.PadLeft(2, '0')[..2]},1,1500", "MM,d,yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out monthDateTime)) + monthDateTime = DateTime.MinValue; + } + else + monthDateTime = DateTime.MinValue; + if (!int.TryParse(day, out int _)) + dayDateTime = DateTime.MinValue; + else + { + if (!DateTime.TryParseExact($"01,{day.PadLeft(2, '0')[..2]},1500", "MM,d,yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dayDateTime)) + dayDateTime = DateTime.MinValue; + } + if (year.Length == 2 && int.TryParse(year, out int _)) + { + if (!DateTime.TryParseExact($"01,01,{year.PadLeft(4, '0')[..4]}", "MM,dd,yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out yearDateTime)) + yearDateTime = DateTime.MinValue; + } + else if (year.Length == 4 && int.TryParse(year, out int _)) + { + if (!DateTime.TryParseExact($"01,01,{year.PadLeft(4, '0')[..4]}", "MM,dd,yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out yearDateTime)) + yearDateTime = DateTime.MinValue; + } + else + yearDateTime = DateTime.MinValue; + result = monthDateTime == DateTime.MinValue ? null : dayDateTime == DateTime.MinValue ? null : yearDateTime == DateTime.MinValue ? null : new(yearDateTime.Year, monthDateTime.Month, dayDateTime.Day); + return result; + } + } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/PersonContainer.cs b/Shared/Models/Stateless/Methods/PersonContainer.cs index 5835a12..80a5858 100644 --- a/Shared/Models/Stateless/Methods/PersonContainer.cs +++ b/Shared/Models/Stateless/Methods/PersonContainer.cs @@ -3,41 +3,96 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; internal abstract class PersonContainer { + private static string[] GetFiles(string personDisplayDirectory) + { + List results = new(); + string[] files; + string extension; + string checkFile; + string directoryName; + List distinct = new(); + string fileNameWithoutExtension; + string personDisplayDirectoryName = Path.GetFileName(personDisplayDirectory); + string[] directories = Directory.GetDirectories(personDisplayDirectory, "*", SearchOption.TopDirectoryOnly); + foreach (string directory in directories) + { + directoryName = Path.GetFileName(directory); + files = Directory.GetFiles(directory, "*", SearchOption.TopDirectoryOnly); + foreach (string file in files) + { + extension = Path.GetExtension(file); + if (extension is not ".json" and not ".pged") + { + results.Add(file); + continue; + } + fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file); + if (string.IsNullOrEmpty(fileNameWithoutExtension) || string.IsNullOrEmpty(personDisplayDirectoryName)) + continue; + else if (fileNameWithoutExtension.Length == 1 && fileNameWithoutExtension[0] == personDisplayDirectoryName[0]) + { + if (distinct.Contains(file)) + throw new NotSupportedException($"Move / Delete <{file}>"); + distinct.Add(file); + } + else if (fileNameWithoutExtension != directoryName) + { + checkFile = Path.Combine(directory, $"{fileNameWithoutExtension}{extension}"); + if (!File.Exists(checkFile)) + { + File.Move(file, checkFile); + results.Add(checkFile); + } + else + { + checkFile = Path.Combine(directory, $"{fileNameWithoutExtension}.txt"); + if (File.Exists(checkFile)) + File.Delete(checkFile); + File.Move(file, checkFile); + } + continue; + } + results.Add(file); + } + } + return results.ToArray(); + } + private static string[] GetFiles(string facesFileNameExtension, string personDisplayDirectory) { - string[] results = Directory.GetFiles(personDisplayDirectory, "*", SearchOption.TopDirectoryOnly); + string[] results; int? id; string checkFile; string? checkDirectory; int? normalizedRectangle; - foreach (string personDisplayDirectoryAllFile in results) + string[] files = Directory.GetFiles(personDisplayDirectory, "*", SearchOption.TopDirectoryOnly); + foreach (string file in files) { - if (personDisplayDirectoryAllFile.EndsWith(".lnk")) + if (file.EndsWith(".lnk")) continue; - (id, normalizedRectangle) = IMapping.GetConverted(facesFileNameExtension, personDisplayDirectoryAllFile); + (id, normalizedRectangle) = IMapping.GetConverted(facesFileNameExtension, file); if (id is not null && normalizedRectangle is not null) continue; - checkDirectory = Path.GetDirectoryName(personDisplayDirectoryAllFile); + checkDirectory = Path.GetDirectoryName(file); if (string.IsNullOrEmpty(checkDirectory)) continue; checkDirectory = Path.Combine(checkDirectory, "_ Invalid"); if (!Directory.Exists(checkDirectory)) _ = Directory.CreateDirectory(checkDirectory); - checkFile = Path.Combine(checkDirectory, Path.GetFileName(personDisplayDirectoryAllFile)); + checkFile = Path.Combine(checkDirectory, Path.GetFileName(file)); if (File.Exists(checkFile)) - File.Delete(personDisplayDirectoryAllFile); + File.Delete(file); else - File.Move(personDisplayDirectoryAllFile, checkFile); + File.Move(file, checkFile); } - results = Directory.GetFiles(personDisplayDirectory, "*", SearchOption.AllDirectories); + results = GetFiles(personDisplayDirectory); return results; } - private static List<(long?, Models.PersonContainer)> GetPersonContainersCollections(string facesFileNameExtension, char[] personCharacters, Dictionary> individuals, char @char, char numberSign, string personDisplayDirectory, string personDisplayDirectoryName, int? approximateYears, List<(string PersonKeyFormatted, Models.PersonBirthday PersonBirthday)> collection) + private static List<(long?, Models.PersonContainer)> GetPersonContainersCollections(string mappingDefaultName, string facesFileNameExtension, char[] personCharacters, Dictionary> individuals, char @char, char numberSign, string personDisplayDirectory, string personDisplayDirectoryName, int? approximateYears, List<(string PersonKeyFormatted, Models.PersonBirthday PersonBirthday)> collection) { List<(long?, Models.PersonContainer)> results = new(); long personKey; - string[] segments; const int zero = 0; Models.Person person; List? individualsLines; @@ -47,7 +102,6 @@ internal abstract class PersonContainer string[] personDisplayDirectoryAllFiles = GetFiles(facesFileNameExtension, personDisplayDirectory); foreach ((string personKeyFormatted, Models.PersonBirthday personBirthday) in collection) { - segments = personDisplayDirectoryName.Split(personCharacters); orderedPersonBirthdays = (from l in collection where !l.PersonKeyFormatted.Contains(numberSign) orderby l.PersonBirthday.Value.Ticks descending select l.PersonBirthday).ToArray(); if (!orderedPersonBirthdays.Any()) personKey = collection[zero].PersonBirthday.Value.Ticks; @@ -59,7 +113,7 @@ internal abstract class PersonContainer } _ = individuals.TryGetValue(personKeyFormatted, out individualsLines); filteredIndividualsLines = individualsLines is null ? null : IPerson.GetFiltered(individualsLines); - person = IPerson.GetPerson(personDisplayDirectoryAllFiles, personKeyFormatted, personKey, segments, filteredIndividualsLines); + person = IPerson.GetPerson(mappingDefaultName, personCharacters, personDisplayDirectoryName, personDisplayDirectoryAllFiles, personKeyFormatted, personKey, filteredIndividualsLines); personContainer = new(approximateYears, @char, person, orderedPersonBirthdays, personDisplayDirectoryAllFiles, personDisplayDirectoryName, personKey, filteredIndividualsLines); results.Add(new(personKey, personContainer)); } @@ -105,7 +159,7 @@ internal abstract class PersonContainer return result; } - private static List<(long?, Models.PersonContainer)> GetPersonContainersGroup(string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, Dictionary> individuals, char @char, string[] personDisplayDirectories) + private static List<(long?, Models.PersonContainer)> GetPersonContainersGroup(string mappingDefaultName, string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, Dictionary> individuals, char @char, string[] personDisplayDirectories) { List<(long?, Models.PersonContainer)> results = new(); string? minusOne; @@ -134,7 +188,7 @@ internal abstract class PersonContainer if (changes.Any(l => l is not null)) continue; if (collection.Any()) - results.AddRange(GetPersonContainersCollections(facesFileNameExtension, personCharacters, individuals, @char, numberSign, personDisplayDirectory, personDisplayDirectoryName, approximateYears, collection)); + results.AddRange(GetPersonContainersCollections(mappingDefaultName, facesFileNameExtension, personCharacters, individuals, @char, numberSign, personDisplayDirectory, personDisplayDirectoryName, approximateYears, collection)); else { personContainer = GetPersonContainer(facesFileNameExtension, @char, personDisplayDirectory, personDisplayDirectoryName, approximateYears); @@ -146,7 +200,7 @@ internal abstract class PersonContainer return results; } - private static Models.PersonContainer[] GetPersonContainersGroups(string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, Dictionary> individuals, string[] groupDirectories) + private static Models.PersonContainer[] GetPersonContainersGroups(string mappingDefaultName, string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, Dictionary> individuals, string[] groupDirectories) { Models.PersonContainer[] results; const int zero = 0; @@ -160,14 +214,14 @@ internal abstract class PersonContainer if (!personCharacters.Contains(groupDirectoryName[zero])) continue; personDisplayDirectories = Directory.GetDirectories(groupDirectory, "*", SearchOption.TopDirectoryOnly); - collection = GetPersonContainersGroup(personBirthdayFormat, facesFileNameExtension, personCharacters, individuals, groupDirectoryName[zero], personDisplayDirectories); + collection = GetPersonContainersGroup(mappingDefaultName, personBirthdayFormat, facesFileNameExtension, personCharacters, individuals, groupDirectoryName[zero], personDisplayDirectories); personContainers.AddRange(collection); } results = (from l in personContainers orderby l.PersonKey is not null, l.PersonKey select l.PersonContainer).ToArray(); return results; } - internal static Models.PersonContainer[] GetPersonContainers(Properties.IStorage storage, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, Dictionary> individuals) + internal static Models.PersonContainer[] GetPersonContainers(Properties.IStorage storage, string mappingDefaultName, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, Dictionary> individuals) { Models.PersonContainer[] results; string a2PeopleSingletonDirectory = Path.Combine(storage.PeopleRootDirectory, "{}"); @@ -184,7 +238,7 @@ internal abstract class PersonContainer if (!groupDirectories.Any()) results = Array.Empty(); else - results = GetPersonContainersGroups(personBirthdayFormat, facesFileNameExtension, personCharacters, individuals, groupDirectories); + results = GetPersonContainersGroups(mappingDefaultName, personBirthdayFormat, facesFileNameExtension, personCharacters, individuals, groupDirectories); return results; } @@ -205,5 +259,5 @@ internal abstract class PersonContainer } return results; } - + } \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/XDirectory.cs b/Shared/Models/Stateless/Methods/XDirectory.cs index 6f94fb1..4b19ef0 100644 --- a/Shared/Models/Stateless/Methods/XDirectory.cs +++ b/Shared/Models/Stateless/Methods/XDirectory.cs @@ -35,6 +35,7 @@ internal abstract partial class XDirectory fileSearchFilter = string.Concat('*', fileSearchFilter); if (!directorySearchFilter.Contains('*')) directorySearchFilter = string.Concat('*', directorySearchFilter); + results.Add(Directory.GetFiles(directory, fileSearchFilter, SearchOption.TopDirectoryOnly)); string[] directories = Directory.GetDirectories(directory, directorySearchFilter, SearchOption.TopDirectoryOnly); foreach (string innerDirectory in directories) results.Add(Directory.GetFiles(innerDirectory, fileSearchFilter, SearchOption.AllDirectories)); diff --git a/Shared/View-by-Distance.Shared.csproj b/Shared/View-by-Distance.Shared.csproj index 48b6b77..3301aeb 100644 --- a/Shared/View-by-Distance.Shared.csproj +++ b/Shared/View-by-Distance.Shared.csproj @@ -3,7 +3,7 @@ enable 10.0 enable - win-x64 + win-x64;linux-x64 net7.0 diff --git a/Tests/UnitTestCalculations.cs b/Tests/UnitTestCalculations.cs index c2842b0..301ded0 100644 --- a/Tests/UnitTestCalculations.cs +++ b/Tests/UnitTestCalculations.cs @@ -61,6 +61,13 @@ public partial class UnitTestCalculations _PropertyConfiguration = propertyConfiguration; } + private static void NonThrowTryCatch() + { + try + { throw new Exception(); } + catch (Exception) { } + } + [TestMethod] public void TestMethodNull() { @@ -71,6 +78,7 @@ public partial class UnitTestCalculations Assert.IsFalse(_WorkingDirectory is null); Assert.IsFalse(_ConfigurationRoot is null); Assert.IsFalse(_PropertyConfiguration is null); + NonThrowTryCatch(); } [TestMethod] @@ -87,29 +95,6 @@ public partial class UnitTestCalculations Assert.IsTrue(age.Value > 42.6092); } - [TestMethod] - public void TestMethodGetApproximateYears() - { - string personDisplayDirectory = @"D:\1) Images A\Images-9b89679-Results\A2) People\9b89679\{}\^\Sydney Dupray^9"; - if (Directory.Exists(Directory.GetDirectoryRoot(personDisplayDirectory)) && Directory.Exists(personDisplayDirectory)) - { - char numberSign = '#'; - string? minusOne = null; - char[] personCharacters = new char[] { '^' }; - string personDisplayDirectoryName = Path.GetFileName(personDisplayDirectory); - string personBirthdayFormat = _Configuration.PropertyConfiguration.PersonBirthdayFormat; - string[] personKeyDirectories = Directory.GetDirectories(personDisplayDirectory, "*", SearchOption.TopDirectoryOnly); - List<(string, PersonBirthday)> collection = IPersonBirthday.GetPersonBirthdays(personBirthdayFormat, personKeyDirectories, personDisplayDirectory, personDisplayDirectoryName); - int? approximateYears = IAge.GetApproximateYears(personCharacters, personDisplayDirectoryName); - if (approximateYears is null) - throw new NullReferenceException(nameof(approximateYears)); - Assert.IsNotNull(approximateYears); - Assert.IsTrue(approximateYears.Value == 9); - string? change = IPersonContainer.VerifyAge(numberSign, personDisplayDirectory, minusOne, personDisplayDirectoryName, approximateYears, collection); - Assert.IsNull(change); - } - } - [TestMethod] public void TestMethodParse() { @@ -138,52 +123,6 @@ public partial class UnitTestCalculations Assert.IsTrue(successful == "_ Manual Copy Successful"); } - [TestMethod] - public void TestMethodDamn() - { - // string name; - // string[] directories; - // string? directoryName; - // string checkDirectory; - // string sourceDirectory = @"F:\Tmp\Phares\Compare\Images 2022-09-15 - 7390c13 - III - Results\E) Distance\2022-09-15\7680 x 4320\7680x4320 - Hog - Large\()"; - // directories = Directory.GetDirectories(sourceDirectory, "*", SearchOption.TopDirectoryOnly); - // foreach (string directory in directories) - // { - // directoryName = Path.GetDirectoryName(directory); - // if (directoryName is null) - // continue; - // name = Path.GetFileName(directory); - // if (name.Length is 1 or 20) - // continue; - // checkDirectory = Path.Combine(directoryName, "b", name); - // Directory.Move(directory, checkDirectory); - // } - // directories = Directory.GetDirectories(Path.Combine(sourceDirectory, "b"), "*", SearchOption.TopDirectoryOnly); - // foreach (string directory in directories) - // { - // directoryName = Path.GetDirectoryName(directory); - // if (directoryName is null) - // continue; - // name = Path.GetFileName(directory); - // if (name.Length is 1 or 20) - // continue; - // checkDirectory = Path.Combine(directoryName, $"{name[..^4]})"); - // if (Directory.Exists(checkDirectory)) - // continue; - // Directory.Move(directory, checkDirectory); - // } - // Assert.IsTrue(true); - } - - [TestMethod] - public void TestMethodDel() - { - string source = @"F:\Tmp\Phares\Compare\Images 2022-09-15 - 7390c13 - III - Results\E) Distance\2022-09-15\7680 x 4320\7680x4320 - Hog - Large\()\(637992984751968513)"; - for (int i = 1; i < 11; i++) - _ = IPath.DeleteEmptyDirectories(source); - Assert.IsTrue(true); - } - [TestMethod] public void TestMethodDirectory() { @@ -302,71 +241,6 @@ public partial class UnitTestCalculations Assert.IsTrue(distance == 1.4142135623730951); } - private static (string?, string, string) Get(string[] segments) - { - (string?, string, string) result; - if ((!segments[0].Contains('#') && (segments[3].Contains('~') || segments[3].Contains('#'))) || (segments[0].Contains('#') && !segments[3].Contains('#'))) - result = new(null, segments[3], segments[4]); - else - result = new(segments[0], segments[3], segments[4]); - return result; - } - - [TestMethod] - public void TestMoveToVerify() - { - string http; - string[] lines; - string? minusOne; - string? minusTwo; - string[] segments; - string[] beforeSegments; - string[] matchDirectories; - string? personKeyFormattedNew; - string? personDisplayDirectory; - string personDisplayDirectoryNew; - string personDisplayDirectoryNameNew; - string personKeyFormattedDirectoryNew; - string sourceDirectory = @""; - string sourceFile = @"\People - C.tsv"; - if (!File.Exists(sourceFile)) - lines = Array.Empty(); - else - lines = File.ReadAllLines(sourceFile); - for (int i = 0; i < lines.Length; i++) - { - if (!lines[i].Contains("https://")) - continue; - segments = lines[i].Split('\t'); - beforeSegments = lines[i - 1].Split('\t'); - if (beforeSegments.Length < 4 || segments.Length < 5) - continue; - matchDirectories = Directory.GetDirectories(sourceDirectory, beforeSegments[0], SearchOption.AllDirectories); - if (matchDirectories.Length != 1) - continue; - personDisplayDirectory = Path.GetDirectoryName(matchDirectories[0]); - if (personDisplayDirectory is null) - continue; - minusOne = Path.GetDirectoryName(personDisplayDirectory); - if (minusOne is null) - continue; - minusTwo = Path.GetDirectoryName(minusOne); - if (minusTwo is null) - continue; - (personKeyFormattedNew, personDisplayDirectoryNameNew, http) = Get(segments); - if (personKeyFormattedNew is null) - continue; - personDisplayDirectoryNew = Path.Combine(minusTwo, "Verify", personDisplayDirectoryNameNew); - if (Directory.Exists(personDisplayDirectoryNew)) - continue; - personKeyFormattedDirectoryNew = Path.Combine(personDisplayDirectoryNew, personKeyFormattedNew); - Directory.Move(personDisplayDirectory, personDisplayDirectoryNew); - _ = Directory.CreateDirectory(personKeyFormattedDirectoryNew); - File.WriteAllText(Path.Combine(personKeyFormattedDirectoryNew, "Facebook.txt"), http); - } - Assert.IsNotNull(lines); - } - [TestMethod] public void TestGetConfidencePercent() { @@ -426,6 +300,23 @@ public partial class UnitTestCalculations File.Move(file, checkFile); } } + NonThrowTryCatch(); + } + + [TestMethod] + public void TestMethodMonth() + { + Assert.AreEqual(IPersonBirthday.GetDate("jan", "17", "1980"), new DateTime(1980, 1, 17)); + Assert.AreEqual(IPersonBirthday.GetDate("january", "17", "1980"), new DateTime(1980, 1, 17)); + Assert.AreEqual(IPersonBirthday.GetDate("f", "17", "1980"), new DateTime(1980, 2, 17)); + Assert.AreEqual(IPersonBirthday.GetDate("01", "17", "1980"), new DateTime(1980, 1, 17)); + Assert.AreEqual(IPersonBirthday.GetDate("1", "17", "1980"), new DateTime(1980, 1, 17)); + Assert.IsNull(IPersonBirthday.GetDate("pan", "17", "1980")); + Assert.IsNull(IPersonBirthday.GetDate("j-a-n-u-a-r-y", "17", "1980")); + Assert.IsNull(IPersonBirthday.GetDate("j", "17", "1980")); + Assert.IsNull(IPersonBirthday.GetDate("13", "17", "1980")); + Assert.IsNull(IPersonBirthday.GetDate("0", "17", "1980")); + NonThrowTryCatch(); } } \ No newline at end of file diff --git a/Tests/UnitTestHardCoded.cs b/Tests/UnitTestHardCoded.cs new file mode 100644 index 0000000..5cb9496 --- /dev/null +++ b/Tests/UnitTestHardCoded.cs @@ -0,0 +1,247 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Phares.Shared; +using Serilog; +using System.Diagnostics; +using System.Reflection; +using View_by_Distance.Shared.Models; +using View_by_Distance.Shared.Models.Stateless.Methods; +using View_by_Distance.Tests.Models; + +namespace View_by_Distance.Tests; + +[TestClass] +public partial class UnitTestHardCoded +{ + + private readonly ILogger _Logger; + 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 UnitTestHardCoded() + { + ILogger logger; + AppSettings appSettings; + string workingDirectory; + Configuration configuration; + IsEnvironment isEnvironment; + IConfigurationRoot configurationRoot; + LoggerConfiguration loggerConfiguration = new(); + Property.Models.Configuration propertyConfiguration; + Assembly assembly = Assembly.GetExecutingAssembly(); + bool debuggerWasAttachedAtLineZero = Debugger.IsAttached || assembly.Location.Contains(@"\bin\Debug"); + 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); + configurationRoot = configurationBuilder.Build(); + appSettings = Models.Binder.AppSettings.Get(configurationRoot); + if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName)) + throw new Exception("Working directory name must have a value!"); + workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName); + Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory); + _ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot); + Log.Logger = loggerConfiguration.CreateLogger(); + logger = Log.ForContext(); + propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot); + configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration); + logger.Information("Complete"); + _Logger = logger; + _AppSettings = appSettings; + _Configuration = configuration; + _IsEnvironment = isEnvironment; + _WorkingDirectory = workingDirectory; + _ConfigurationRoot = configurationRoot; + _PropertyConfiguration = propertyConfiguration; + } + + private static void NonThrowTryCatch() + { + try + { throw new Exception(); } + catch (Exception) { } + } + + [TestMethod] + public void TestMethodNull() + { + Assert.IsFalse(_Logger is null); + Assert.IsFalse(_AppSettings is null); + Assert.IsFalse(_Configuration is null); + Assert.IsFalse(_IsEnvironment is null); + Assert.IsFalse(_WorkingDirectory is null); + Assert.IsFalse(_ConfigurationRoot is null); + Assert.IsFalse(_PropertyConfiguration is null); + NonThrowTryCatch(); + } + + [TestMethod] + public void TestMethodDel() + { + string source = @"F:\Tmp\Phares\Compare\Images 2022-09-15 - 7390c13 - III - Results\E) Distance\2022-09-15\7680 x 4320\7680x4320 - Hog - Large\()\(637992984751968513)"; + for (int i = 1; i < 11; i++) + _ = IPath.DeleteEmptyDirectories(source); + Assert.IsTrue(true); + NonThrowTryCatch(); + } + + [TestMethod] + public void TestMethodGetApproximateYears() + { + string personDisplayDirectory = @"D:\1) Images A\Images-9b89679-Results\A2) People\9b89679\{}\^\Sydney Dupray^9"; + if (Directory.Exists(Directory.GetDirectoryRoot(personDisplayDirectory)) && Directory.Exists(personDisplayDirectory)) + { + char numberSign = '#'; + string? minusOne = null; + char[] personCharacters = new char[] { '^' }; + string personDisplayDirectoryName = Path.GetFileName(personDisplayDirectory); + string personBirthdayFormat = _Configuration.PropertyConfiguration.PersonBirthdayFormat; + string[] personKeyDirectories = Directory.GetDirectories(personDisplayDirectory, "*", SearchOption.TopDirectoryOnly); + List<(string, PersonBirthday)> collection = IPersonBirthday.GetPersonBirthdays(personBirthdayFormat, personKeyDirectories, personDisplayDirectory, personDisplayDirectoryName); + int? approximateYears = IAge.GetApproximateYears(personCharacters, personDisplayDirectoryName); + if (approximateYears is null) + throw new NullReferenceException(nameof(approximateYears)); + Assert.IsNotNull(approximateYears); + Assert.IsTrue(approximateYears.Value == 9); + string? change = IPersonContainer.VerifyAge(numberSign, personDisplayDirectory, minusOne, personDisplayDirectoryName, approximateYears, collection); + Assert.IsNull(change); + } + NonThrowTryCatch(); + } + + [TestMethod] + public void TestMethodDamn() + { + // string name; + // string[] directories; + // string? directoryName; + // string checkDirectory; + // string sourceDirectory = @"F:\Tmp\Phares\Compare\Images 2022-09-15 - 7390c13 - III - Results\E) Distance\2022-09-15\7680 x 4320\7680x4320 - Hog - Large\()"; + // directories = Directory.GetDirectories(sourceDirectory, "*", SearchOption.TopDirectoryOnly); + // foreach (string directory in directories) + // { + // directoryName = Path.GetDirectoryName(directory); + // if (directoryName is null) + // continue; + // name = Path.GetFileName(directory); + // if (name.Length is 1 or 20) + // continue; + // checkDirectory = Path.Combine(directoryName, "b", name); + // Directory.Move(directory, checkDirectory); + // } + // directories = Directory.GetDirectories(Path.Combine(sourceDirectory, "b"), "*", SearchOption.TopDirectoryOnly); + // foreach (string directory in directories) + // { + // directoryName = Path.GetDirectoryName(directory); + // if (directoryName is null) + // continue; + // name = Path.GetFileName(directory); + // if (name.Length is 1 or 20) + // continue; + // checkDirectory = Path.Combine(directoryName, $"{name[..^4]})"); + // if (Directory.Exists(checkDirectory)) + // continue; + // Directory.Move(directory, checkDirectory); + // } + // Assert.IsTrue(true); + } + + [TestMethod] + public void TestMethodDel2() + { + string source = @"F:\Tmp\Phares\Compare\Images 2022-09-15 - 7390c13 - III - Results\E) Distance\2022-09-15\7680 x 4320\7680x4320 - Hog - Large\()\(637992984751968513)"; + for (int i = 1; i < 11; i++) + _ = IPath.DeleteEmptyDirectories(source); + Assert.IsTrue(true); + NonThrowTryCatch(); + } + + private static (string?, string, string) Get(string[] segments) + { + (string?, string, string) result; + if ((!segments[0].Contains('#') && (segments[3].Contains('~') || segments[3].Contains('#'))) || (segments[0].Contains('#') && !segments[3].Contains('#'))) + result = new(null, segments[3], segments[4]); + else + result = new(segments[0], segments[3], segments[4]); + return result; + } + + [TestMethod] + public void TestMoveToVerify() + { + string http; + string[] lines; + string? minusOne; + string? minusTwo; + string[] segments; + string[] beforeSegments; + string[] matchDirectories; + string? personKeyFormattedNew; + string? personDisplayDirectory; + string personDisplayDirectoryNew; + string personDisplayDirectoryNameNew; + string personKeyFormattedDirectoryNew; + string sourceDirectory = @""; + string sourceFile = @"\People - C.tsv"; + if (!File.Exists(sourceFile)) + lines = Array.Empty(); + else + lines = File.ReadAllLines(sourceFile); + for (int i = 0; i < lines.Length; i++) + { + if (!lines[i].Contains("https://")) + continue; + segments = lines[i].Split('\t'); + beforeSegments = lines[i - 1].Split('\t'); + if (beforeSegments.Length < 4 || segments.Length < 5) + continue; + matchDirectories = Directory.GetDirectories(sourceDirectory, beforeSegments[0], SearchOption.AllDirectories); + if (matchDirectories.Length != 1) + continue; + personDisplayDirectory = Path.GetDirectoryName(matchDirectories[0]); + if (personDisplayDirectory is null) + continue; + minusOne = Path.GetDirectoryName(personDisplayDirectory); + if (minusOne is null) + continue; + minusTwo = Path.GetDirectoryName(minusOne); + if (minusTwo is null) + continue; + (personKeyFormattedNew, personDisplayDirectoryNameNew, http) = Get(segments); + if (personKeyFormattedNew is null) + continue; + personDisplayDirectoryNew = Path.Combine(minusTwo, "Verify", personDisplayDirectoryNameNew); + if (Directory.Exists(personDisplayDirectoryNew)) + continue; + personKeyFormattedDirectoryNew = Path.Combine(personDisplayDirectoryNew, personKeyFormattedNew); + Directory.Move(personDisplayDirectory, personDisplayDirectoryNew); + _ = Directory.CreateDirectory(personKeyFormattedDirectoryNew); + File.WriteAllText(Path.Combine(personKeyFormattedDirectoryNew, "Facebook.txt"), http); + } + Assert.IsNotNull(lines); + NonThrowTryCatch(); + } + + [TestMethod] + public void TestMethodRenameAbandoned() + { + string checkFile; + string source = @"D:\1) Images A\Images-9b89679-Results\A2) People\9b89679\{}\!\Abandoned"; + string[] files = Directory.GetFiles(source, "*.abd", SearchOption.TopDirectoryOnly); + foreach (string file in files) + { + checkFile = file[..^4]; + if (File.Exists(checkFile)) + continue; + File.Move(file, checkFile); + } + Assert.IsTrue(true); + NonThrowTryCatch(); + } + +} \ No newline at end of file diff --git a/View-by-Distance-MKLink-Console.sln b/View-by-Distance-MKLink-Console.sln index 3bbd8f8..41c9d4d 100644 --- a/View-by-Distance-MKLink-Console.sln +++ b/View-by-Distance-MKLink-Console.sln @@ -49,6 +49,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "View-by-Distance.Shared", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Move-By-Id", "Move-By-Id\Move-By-Id.csproj", "{0FDFBC71-3801-483F-A4AC-CC8CF857D54F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Person", "Person\Person.csproj", "{C5003A39-334B-444B-9873-39B26E58D667}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -154,5 +156,9 @@ Global {0FDFBC71-3801-483F-A4AC-CC8CF857D54F}.Debug|Any CPU.Build.0 = Debug|Any CPU {0FDFBC71-3801-483F-A4AC-CC8CF857D54F}.Release|Any CPU.ActiveCfg = Release|Any CPU {0FDFBC71-3801-483F-A4AC-CC8CF857D54F}.Release|Any CPU.Build.0 = Release|Any CPU + {C5003A39-334B-444B-9873-39B26E58D667}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C5003A39-334B-444B-9873-39B26E58D667}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C5003A39-334B-444B-9873-39B26E58D667}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C5003A39-334B-444B-9873-39B26E58D667}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal