Facebook logic, IsDefaultName, GetFiles update and

HardCoded tests
This commit is contained in:
Mike Phares 2023-04-01 11:29:00 -07:00
parent b0b6864841
commit ba5bc6347c
36 changed files with 1396 additions and 402 deletions

17
.vscode/launch.json vendored
View File

@ -193,6 +193,23 @@
"stopAtEntry": false, "stopAtEntry": false,
"requireExactSource": 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", "name": "Rename",
"type": "coreclr", "type": "coreclr",

59
.vscode/tasks.json vendored
View File

@ -1,6 +1,65 @@
{ {
"version": "2.0.0", "version": "2.0.0",
"options": {
"env": {
"serverUserSecretsId": "7ca5318a-9332-4217-b9d8-cae696629934"
}
},
"tasks": [ "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", "label": "build",
"command": "dotnet", "command": "dotnet",

View File

@ -123,10 +123,10 @@ public partial class DlibDotNet
if (rootResultsDirectory is null) if (rootResultsDirectory is null)
throw new Exception(); throw new Exception();
Storage storage = new(rootDirectory, rootResultsDirectory, peopleRootDirectory); Storage storage = new(rootDirectory, rootResultsDirectory, peopleRootDirectory);
_GEDCOMFile = Path.GetFullPath(string.Concat(peopleRootDirectory, configuration.GEDCOMFile));
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(peopleRootDirectory, "{}")); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(Path.Combine(peopleRootDirectory, "{}"));
_GEDCOMFile = string.IsNullOrEmpty(configuration.GEDCOMFile) ? null : Path.GetFullPath(string.Concat(peopleRootDirectory, configuration.GEDCOMFile));
(_GEDCOMHeaderLines, Dictionary<string, List<string>> individuals, _GEDCOMFooterLines) = Shared.Models.Stateless.Methods.IPerson.GetIndividuals(_GEDCOMFile); (_GEDCOMHeaderLines, Dictionary<string, List<string>> 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( (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); 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) private string SaveUrlAndGetNewRootDirectory(Container container)
{ {
if (_Log is null) if (_Log is null)
@ -1058,8 +1033,11 @@ public partial class DlibDotNet
{ {
int t; int t;
Container[] containers; Container[] containers;
A_Property propertyLogic;
string eDistanceContentDirectory; string eDistanceContentDirectory;
string? a2PeopleContentDirectory; string? a2PeopleContentDirectory;
string aResultsFullGroupDirectory;
string bResultsFullGroupDirectory;
string cResultsFullGroupDirectory; string cResultsFullGroupDirectory;
string dResultsFullGroupDirectory; string dResultsFullGroupDirectory;
string d2ResultsFullGroupDirectory; string d2ResultsFullGroupDirectory;
@ -1067,7 +1045,7 @@ public partial class DlibDotNet
string fPhotoPrismSingletonDirectory; string fPhotoPrismSingletonDirectory;
Dictionary<long, List<int>> personKeyToIds; Dictionary<long, List<int>> personKeyToIds;
Dictionary<string, List<MappingFromPhotoPrism>> fileNameToCollection; Dictionary<string, List<MappingFromPhotoPrism>> fileNameToCollection;
(string aResultsFullGroupDirectory, string bResultsFullGroupDirectory) = GetResultsFullGroupDirectories(); (aResultsFullGroupDirectory, bResultsFullGroupDirectory) = GetResultsFullGroupDirectories();
string a2PeopleSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "{}"); string a2PeopleSingletonDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "{}");
int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds); int totalSeconds = (int)Math.Floor(new TimeSpan(DateTime.Now.Ticks - ticks).TotalSeconds);
string message = $") Building Container(s) - {totalSeconds} total second(s)"; 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); (t, containers) = Shared.Models.Stateless.Methods.IContainer.GetContainers(_Configuration.PropertyConfiguration, aPropertySingletonDirectory);
progressBar.Tick(); progressBar.Tick();
} }
Container? container = AreAllSameEndsWith(argZero, containers); propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, aResultsFullGroupDirectory);
A_Property propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, aResultsFullGroupDirectory); if (containers.Length != 1)
B_Metadata metadata = new(_Configuration.PropertyConfiguration, _Configuration.ForceMetadataLastWriteTimeToCreationTime, _Configuration.PropertiesChangedForMetadata, bResultsFullGroupDirectory);
if (!_ArgZeroIsConfigurationRootDirectory || container is null)
{ {
a2PeopleContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "([])"); a2PeopleContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(A2_People), "([])");
eDistanceContentDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(E_Distance), "()"); 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)}", "()"); eDistanceContentDirectory = Path.Combine($"{Path.GetPathRoot(argZero)}", "()");
fPhotoPrismContentDirectory = Path.Combine($"{Path.GetPathRoot(argZero)}", "()"); fPhotoPrismContentDirectory = Path.Combine($"{Path.GetPathRoot(argZero)}", "()");
fPhotoPrismSingletonDirectory = 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++) for (int i = 1; i < 10; i++)
{ {
resultsGroupDirectory = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, string.Empty, create: true); resultsGroupDirectory = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, string.Empty, create: true);
@ -1106,9 +1082,11 @@ public partial class DlibDotNet
} }
argZero = newRootDirectory; argZero = newRootDirectory;
_Configuration.PropertyConfiguration.ChangeRootDirectory(newRootDirectory); _Configuration.PropertyConfiguration.ChangeRootDirectory(newRootDirectory);
(aResultsFullGroupDirectory, bResultsFullGroupDirectory) = GetResultsFullGroupDirectories();
propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), create: false); propertyRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, nameof(A_Property), create: false);
propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, aResultsFullGroupDirectory); 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); 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); MapLogic mapLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, _PersonContainers, ticks, a2PeopleSingletonDirectory, eDistanceContentDirectory);
personKeyToIds = mapLogic.GetPersonKeyToIds(); personKeyToIds = mapLogic.GetPersonKeyToIds();
@ -1128,7 +1106,7 @@ public partial class DlibDotNet
File.WriteAllText(Path.Combine(eDistanceContentDirectory, $"{ticks}.json"), json); File.WriteAllText(Path.Combine(eDistanceContentDirectory, $"{ticks}.json"), json);
foreach (string outputResolution in _Configuration.OutputResolutions) foreach (string outputResolution in _Configuration.OutputResolutions)
{ {
if (_PropertyRootExistedBefore || container is not null) if (_PropertyRootExistedBefore)
break; break;
if (!string.IsNullOrEmpty(a2PeopleContentDirectory) && _Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution)) if (!string.IsNullOrEmpty(a2PeopleContentDirectory) && _Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution))
mapLogic.SaveShortcutsForOutputResolutionsPreMapLogic(eDistanceContentDirectory, personKeyToIds, idToLocationContainers, mappingCollection); mapLogic.SaveShortcutsForOutputResolutionsPreMapLogic(eDistanceContentDirectory, personKeyToIds, idToLocationContainers, mappingCollection);

View File

@ -138,8 +138,7 @@ public class Configuration
throw new NullReferenceException(nameof(configuration.GEDCOMFile)); throw new NullReferenceException(nameof(configuration.GEDCOMFile));
if (configuration.IgnoreExtensions is null) if (configuration.IgnoreExtensions is null)
throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); throw new NullReferenceException(nameof(configuration.IgnoreExtensions));
if (configuration.IgnoreRelativePaths is null) configuration.IgnoreRelativePaths ??= Array.Empty<string>();
throw new NullReferenceException(nameof(configuration.IgnoreRelativePaths));
configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions ??= Array.Empty<string>(); configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions ??= Array.Empty<string>();
configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions ??= Array.Empty<string>(); configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions ??= Array.Empty<string>();
if (configuration.LocationDigits is null) if (configuration.LocationDigits is null)

View File

@ -20,14 +20,15 @@
"xFocusDirectory": "/Hawaii 2022", "xFocusDirectory": "/Hawaii 2022",
"FocusModel": "", "FocusModel": "",
"xFocusModel": "NIKON D3400", "xFocusModel": "NIKON D3400",
"GEDCOMFile": "/([])/638158579618344864/638158579618344864-Export.ged", "GEDCOMFile": "",
"xGEDCOMFile": "/([])/638158748933377321/638158748933377321-Export-Copy.ged",
"PersonCharactersCopyCount": 0, "PersonCharactersCopyCount": 0,
"xPersonCharactersCopyCount": 2, "xPersonCharactersCopyCount": 2,
"xRootDirectory": "D:/Tmp/phares/Pictures", "xRootDirectory": "D:/Tmp/phares/Pictures",
"xxRootDirectory": "D:/Tmp/Phares/Compare/Corrupt", "xxRootDirectory": "D:/Tmp/Phares/Compare/Corrupt",
"xxxRootDirectory": "D:/2) Images B/Not-Copy-Copy-9b89679", "xxxRootDirectory": "D:/2) Images B/Not-Copy-Copy-9b89679",
"RootDirectory": "D:/1) Images A/Images-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, "SaveSortingWithoutPerson": true,
"SkipOlderThanDays": null, "SkipOlderThanDays": null,
"xSkipOlderThanDays": 2200, "xSkipOlderThanDays": 2200,
@ -98,116 +99,7 @@
"/!/Wax" "/!/Wax"
], ],
"IgnoreRelativePaths": [ "IgnoreRelativePaths": [
"3757 W Whitman 2017", "zzz Phares Slides ####"
"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"
], ],
"MixedYearRelativePaths": [ "MixedYearRelativePaths": [
"Edited", "Edited",

View File

@ -1127,7 +1127,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
directory = Path.Combine($"{eDistanceContentDirectory}---", "Person Key Shortcuts", personKeyFormatted, directoryName); directory = Path.Combine($"{eDistanceContentDirectory}---", "Person Key Shortcuts", personKeyFormatted, directoryName);
fileName = Path.Combine(directory, $"{mapping.MappingFromItem.ImageFileHolder.Name}.lnk"); 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)); 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; continue;
directory = Path.Combine($"{eDistanceContentDirectory}---", "Name Shortcuts", mapping.MappingFromPerson.DisplayDirectoryName, directoryName); directory = Path.Combine($"{eDistanceContentDirectory}---", "Name Shortcuts", mapping.MappingFromPerson.DisplayDirectoryName, directoryName);
fileName = Path.Combine(directory, $"{mapping.MappingFromItem.ImageFileHolder.Name}.lnk"); fileName = Path.Combine(directory, $"{mapping.MappingFromItem.ImageFileHolder.Name}.lnk");

View File

@ -29,7 +29,7 @@ internal abstract class MapLogic
if (personKeys.Contains(personKey)) if (personKeys.Contains(personKey))
continue; continue;
personBirthday = IPersonBirthday.GetPersonBirthday(personKey); 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); personContainer = new(approximateYears, person, new PersonBirthday[] { personBirthday }, personDisplayDirectoryAllFiles, configuration.MappingDefaultName, personKey);
results.Add(personContainer); 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!"); throw new Exception($"Move personKey directories up one from {forceSingleImageHumanized} and delete {forceSingleImageHumanized} directory!");
if (personKeyFormatted.Length != configuration.PersonBirthdayFormat.Length) if (personKeyFormatted.Length != configuration.PersonBirthdayFormat.Length)
continue; 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; personFirstInitialDirectory = personNameDirectory;
else else
{ {
@ -167,6 +167,8 @@ internal abstract class MapLogic
continue; continue;
} }
personFirstInitialDirectory = Path.Combine(yearDirectory, personFirstInitial.ToString()); personFirstInitialDirectory = Path.Combine(yearDirectory, personFirstInitial.ToString());
if (Directory.Exists(personFirstInitialDirectory))
throw new Exception("Forgot to ...");
Directory.Move(personNameDirectory, personFirstInitialDirectory); Directory.Move(personNameDirectory, personFirstInitialDirectory);
files = Directory.GetFiles(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly); files = Directory.GetFiles(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly);
} }
@ -300,7 +302,7 @@ internal abstract class MapLogic
personDisplayDirectory = Path.Combine(personDisplayDirectoryNames); personDisplayDirectory = Path.Combine(personDisplayDirectoryNames);
if (!personKeyFormattedToPersonContainer.ContainsKey(personKeyFormatted)) if (!personKeyFormattedToPersonContainer.ContainsKey(personKeyFormatted))
{ {
personContainer = new(configuration.PersonCharacters.ToArray(), personBirthday, personDisplayDirectoryName); personContainer = new(configuration.MappingDefaultName, configuration.PersonCharacters.ToArray(), personBirthday, personDisplayDirectoryName);
personKeyFormattedToPersonContainer.Add(personKeyFormatted, personContainer); personKeyFormattedToPersonContainer.Add(personKeyFormatted, personContainer);
} }
if (personDisplayDirectoryName.Length != 1 && personDisplayDirectoryName != configuration.MappingDefaultName && !personDisplayDirectoryTo.ContainsKey(personDisplayDirectory)) if (personDisplayDirectoryName.Length != 1 && personDisplayDirectoryName != configuration.MappingDefaultName && !personDisplayDirectoryTo.ContainsKey(personDisplayDirectory))
@ -356,9 +358,10 @@ internal abstract class MapLogic
{ {
int result = 0; int result = 0;
int? id; int? id;
string checkFile;
int? normalizedRectangle; int? normalizedRectangle;
List<int> normalizedRectangles; List<int> normalizedRectangles;
string newestPersonKeyFormatted; string? newestPersonKeyFormatted;
string personDisplayDirectoryName; string personDisplayDirectoryName;
List<string> duplicateMappedFaceFiles = new(); List<string> duplicateMappedFaceFiles = new();
Dictionary<int, List<int>> idToNormalizedRectangles = new(); Dictionary<int, List<int>> idToNormalizedRectangles = new();
@ -369,6 +372,14 @@ internal abstract class MapLogic
foreach ((string personKeyFormatted, string[] personDisplayDirectoryNames, string mappedFaceFile) in collection) foreach ((string personKeyFormatted, string[] personDisplayDirectoryNames, string mappedFaceFile) in collection)
{ {
progressBar.Tick(); 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); (id, normalizedRectangle) = IMapping.GetConverted(configuration.FacesFileNameExtension, mappedFaceFile);
if (id is null || normalizedRectangle is null) if (id is null || normalizedRectangle is null)
{ {
@ -380,10 +391,6 @@ internal abstract class MapLogic
normalizedRectangles = idToNormalizedRectangles[id.Value]; normalizedRectangles = idToNormalizedRectangles[id.Value];
normalizedRectangles.Add(normalizedRectangle.Value); normalizedRectangles.Add(normalizedRectangle.Value);
idToNormalizedRectangles[id.Value].Add(normalizedRectangle.Value); idToNormalizedRectangles[id.Value].Add(normalizedRectangle.Value);
if (!personKeyFormattedToNewestPersonKeyFormatted.ContainsKey(personKeyFormatted))
newestPersonKeyFormatted = personKeyFormatted;
else
newestPersonKeyFormatted = personKeyFormattedToNewestPersonKeyFormatted[personKeyFormatted];
personDisplayDirectoryName = personDisplayDirectoryNames[^1]; personDisplayDirectoryName = personDisplayDirectoryNames[^1];
if (string.IsNullOrEmpty(personDisplayDirectoryName)) if (string.IsNullOrEmpty(personDisplayDirectoryName))
continue; continue;
@ -398,32 +405,6 @@ internal abstract class MapLogic
return new(result, duplicateMappedFaceFiles.Count); return new(result, duplicateMappedFaceFiles.Count);
} }
private static double GetStandardDeviation(IEnumerable<long> 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<double> GetSumCollection(long[] collection)
{
List<double> 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<PersonContainer> GetNotMappedPersonContainers(Configuration configuration, List<PersonContainer> personContainers, List<long> personKeys, long[] personKeyCollection) private static List<PersonContainer> GetNotMappedPersonContainers(Configuration configuration, List<PersonContainer> personContainers, List<long> personKeys, long[] personKeyCollection)
{ {
List<PersonContainer> results = new(); List<PersonContainer> results = new();

View File

@ -3,7 +3,7 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<LangVersion>10.0</LangVersion> <LangVersion>10.0</LangVersion>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>WinExe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
</PropertyGroup> </PropertyGroup>

26
Person/.vscode/launch.json vendored Normal file
View File

@ -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"
}
]
}

41
Person/.vscode/tasks.json vendored Normal file
View File

@ -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"
}
]
}

View File

@ -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;
}
}

View File

@ -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<AppSettings>();
result = Get(appSettings);
return result;
}
}

View File

@ -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<Configuration>();
else
{
string environmentName = IsEnvironment.GetEnvironmentName(isEnvironment);
string section = string.Concat(environmentName, ":", nameof(Configuration));
IConfigurationSection configurationSection = configurationRoot.GetSection(section);
configuration = configurationSection.Get<Configuration>();
}
result = Get(configuration);
result.SetAndUpdate(propertyConfiguration);
return result;
}
}

View File

@ -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();
}
}

View File

@ -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);
}

232
Person/Person.cs Normal file
View File

@ -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<string> 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<Person>();
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(". . .");
}
}

59
Person/Person.csproj Normal file
View File

@ -0,0 +1,59 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>10.0</LangVersion>
<Nullable>enable</Nullable>
<OutputType>Exe</OutputType>
<RuntimeIdentifiers>win-x64;linux-x64</RuntimeIdentifiers>
<TargetFramework>net7.0</TargetFramework>
<UserSecretsId>7ca5318a-9332-4217-b9d8-cae696629934</UserSecretsId>
</PropertyGroup>
<PropertyGroup>
<PackageId>Phares.View.by.Distance.Person</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>7.0.101.1</Version>
<Authors>Mike Phares</Authors>
<Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<PropertyGroup>
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
<IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX>
<IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
</PropertyGroup>
<PropertyGroup Condition="'$(IsWindows)'=='true'">
<DefineConstants>Windows</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsOSX)'=='true'">
<DefineConstants>OSX</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsLinux)'=='true'">
<DefineConstants>Linux</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'browser-wasm'">
<SupportedPlatform Include="browser" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Humanizer.Core" Version="2.14.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Serilog" Version="2.12.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Property\Property.csproj" />
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="appsettings.Development.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

70
Person/Program.cs Normal file
View File

@ -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<string> 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<Program>();
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<string>());
}
}

View File

@ -0,0 +1,17 @@
{
"Logging": {
"LogLevel": {
"Log4netProvider": "Debug"
}
},
"MaxDegreeOfParallelism": 6,
"Serilog": {
"MinimumLevel": "Debug"
},
"Windows": {
"Configuration": {
"RootDirectory": "C:/",
"VerifyToSeason": []
}
}
}

120
Person/appsettings.json Normal file
View File

@ -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"
}

View File

@ -4,7 +4,7 @@
<LangVersion>10.0</LangVersion> <LangVersion>10.0</LangVersion>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>library</OutputType> <OutputType>library</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifiers>win-x64;linux-x64</RuntimeIdentifiers>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>

View File

@ -2,6 +2,7 @@
using Phares.Shared; using Phares.Shared;
using Serilog; using Serilog;
using ShellProgressBar; using ShellProgressBar;
using System.Text.Json;
using View_by_Distance.Rename.Models; using View_by_Distance.Rename.Models;
using View_by_Distance.Shared.Models; using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Methods; using View_by_Distance.Shared.Models.Methods;
@ -35,7 +36,6 @@ public class Rename
Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration); Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration);
_PropertyConfiguration = propertyConfiguration; _PropertyConfiguration = propertyConfiguration;
_Configuration = configuration; _Configuration = configuration;
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
propertyConfiguration.Update(); propertyConfiguration.Update();
string? comparePathRoot = Path.GetDirectoryName(appSettings.ComparePathsFile); string? comparePathRoot = Path.GetDirectoryName(appSettings.ComparePathsFile);
if (comparePathRoot is null || comparePathRoot == propertyConfiguration.RootDirectory) if (comparePathRoot is null || comparePathRoot == propertyConfiguration.RootDirectory)
@ -43,7 +43,7 @@ public class Rename
log.Information(propertyConfiguration.RootDirectory); log.Information(propertyConfiguration.RootDirectory);
Verify(); Verify();
string json = File.ReadAllText(appSettings.ComparePathsFile); string json = File.ReadAllText(appSettings.ComparePathsFile);
MatchNginx[]? matchNginxCollection = System.Text.Json.JsonSerializer.Deserialize<MatchNginx[]>(json); MatchNginx[]? matchNginxCollection = JsonSerializer.Deserialize<MatchNginx[]>(json);
if (matchNginxCollection is null) if (matchNginxCollection is null)
throw new NullReferenceException(nameof(matchNginxCollection)); throw new NullReferenceException(nameof(matchNginxCollection));
if (matchNginxCollection.Length == 0 && matchNginxCollection[0].ConvertedPath.Contains("~~~")) if (matchNginxCollection.Length == 0 && matchNginxCollection[0].ConvertedPath.Contains("~~~"))
@ -52,7 +52,7 @@ public class Rename
Rename2000(matchNginxCollection); Rename2000(matchNginxCollection);
else if (matchNginxCollection.Any()) else if (matchNginxCollection.Any())
{ {
List<string> lines = RenameFilesInDirectories(log, options, matchNginxCollection); List<string> lines = RenameFilesInDirectories(log, matchNginxCollection);
File.WriteAllLines($"D:/Tmp/Phares/{DateTime.Now.Ticks}.tsv", lines); File.WriteAllLines($"D:/Tmp/Phares/{DateTime.Now.Ticks}.tsv", lines);
if (comparePathRoot != Path.GetPathRoot(matchNginxCollection[0].ConvertedPath)) if (comparePathRoot != Path.GetPathRoot(matchNginxCollection[0].ConvertedPath))
_ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(comparePathRoot); _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(comparePathRoot);
@ -71,6 +71,8 @@ public class Rename
{ } { }
if (_WorkingDirectory is null) if (_WorkingDirectory is null)
{ } { }
if (_PropertyConfiguration is null)
{ }
} }
private static void MoveMatches(MatchNginx matchNginx) private static void MoveMatches(MatchNginx matchNginx)
@ -384,7 +386,7 @@ public class Rename
return results; return results;
} }
private List<string> RenameFilesInDirectories(ILogger log, ProgressBarOptions options, MatchNginx[] matchNginxCollection) private List<string> RenameFilesInDirectories(ILogger log, MatchNginx[] matchNginxCollection)
{ {
List<string> results = new(); List<string> results = new();
string[] files; string[] files;
@ -393,6 +395,7 @@ public class Rename
List<(FileHolder, string)> toDoCollection; List<(FileHolder, string)> toDoCollection;
List<(FileHolder, string)> verifiedToDoCollection; List<(FileHolder, string)> verifiedToDoCollection;
List<string> allFiles = GetAllFiles(matchNginxCollection); List<string> allFiles = GetAllFiles(matchNginxCollection);
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
for (int i = 1; i < 3; i++) for (int i = 1; i < 3; i++)
{ {
message = $"{i}) Renaming files"; message = $"{i}) Renaming files";

View File

@ -3,7 +3,7 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<LangVersion>10.0</LangVersion> <LangVersion>10.0</LangVersion>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<OutputType>WinExe</OutputType> <OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
</PropertyGroup> </PropertyGroup>

View File

@ -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": "", "CopyTo": "",
"Logging": { "Logging": {
"LogLevel": { "LogLevel": {

View File

@ -28,8 +28,8 @@ public class PersonContainer : Properties.IPersonContainer
FilteredIndividualsLines = filteredIndividualsLines; FilteredIndividualsLines = filteredIndividualsLines;
} }
public PersonContainer(char[] personCharacters, PersonBirthday birthday, string displayDirectoryName) : public PersonContainer(string mappingDefaultName, 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<string>(), displayDirectoryName, birthday.Value.Ticks, null) this(Stateless.Methods.IAge.GetApproximateYears(personCharacters, displayDirectoryName), null, Stateless.Methods.IPerson.GetPerson(mappingDefaultName, personCharacters, displayDirectoryName, birthday.Value.Ticks, birthday), new PersonBirthday[] { birthday }, Array.Empty<string>(), displayDirectoryName, birthday.Value.Ticks, null)
{ } { }
public PersonContainer(int? approximateYears, PersonBirthday birthdays, string displayDirectoryName, long key) : public PersonContainer(int? approximateYears, PersonBirthday birthdays, string displayDirectoryName, long key) :

View File

@ -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) => string TestStatic_GetFileFullName(Properties.IStorage storage, string personBirthdayFormat, Models.Person person) =>
GetFileFullName(storage, personBirthdayFormat, person); GetFileFullName(storage, personBirthdayFormat, person);
static string GetFileFullName(Properties.IStorage storage, string personBirthdayFormat, Models.Person person) => static string GetFileFullName(Properties.IStorage storage, string personBirthdayFormat, Models.Person person) =>
IPersonBirthday.GetFileFullName(storage, personBirthdayFormat, person.Birthday); IPersonBirthday.GetFileFullName(storage, personBirthdayFormat, person.Birthday);
Models.Person TestStatic_GetPerson(char[] personCharacters, string personDisplayDirectoryName, long personKey, Models.PersonBirthday personBirthday) => Models.Person TestStatic_GetPerson(string mappingDefaultName, char[] personCharacters, string personDisplayDirectoryName, long personKey, Models.PersonBirthday personBirthday) =>
GetPerson(personCharacters, personDisplayDirectoryName, personKey, personBirthday); GetPerson(mappingDefaultName, personCharacters, personDisplayDirectoryName, personKey, personBirthday);
static Models.Person GetPerson(char[] personCharacters, string personDisplayDirectoryName, long personKey, Models.PersonBirthday personBirthday) => static Models.Person GetPerson(string mappingDefaultName, char[] personCharacters, string personDisplayDirectoryName, long personKey, Models.PersonBirthday personBirthday) =>
Person.GetPerson(Array.Empty<string>(), null, personKey, personBirthday, personDisplayDirectoryName.Split(personCharacters), null); Person.GetPerson(mappingDefaultName, personCharacters, personDisplayDirectoryName, Array.Empty<string>(), null, personKey, personBirthday, null);
Models.Person TestStatic_GetPerson(string[] personDisplayDirectoryAllFiles, string personKeyFormatted, long personKey, string[] segments, string[]? filteredIndividualsLines) => Models.Person TestStatic_GetPerson(string mappingDefaultName, char[] personCharacters, string personDisplayDirectoryName, string[] personDisplayDirectoryAllFiles, string personKeyFormatted, long personKey, string[]? filteredIndividualsLines) =>
GetPerson(personDisplayDirectoryAllFiles, personKeyFormatted, personKey, segments, filteredIndividualsLines); GetPerson(mappingDefaultName, personCharacters, personDisplayDirectoryName, personDisplayDirectoryAllFiles, personKeyFormatted, personKey, filteredIndividualsLines);
static Models.Person GetPerson(string[] personDisplayDirectoryAllFiles, string personKeyFormatted, long personKey, string[] segments, string[]? filteredIndividualsLines) => static Models.Person GetPerson(string mappingDefaultName, char[] personCharacters, string personDisplayDirectoryName, string[] personDisplayDirectoryAllFiles, string personKeyFormatted, long personKey, string[]? filteredIndividualsLines) =>
Person.GetPerson(personDisplayDirectoryAllFiles, personKeyFormatted, personKey, IPersonBirthday.GetPersonBirthday(personKey), segments, filteredIndividualsLines); Person.GetPerson(mappingDefaultName, personCharacters, personDisplayDirectoryName, personDisplayDirectoryAllFiles, personKeyFormatted, personKey, IPersonBirthday.GetPersonBirthday(personKey), filteredIndividualsLines);
(string[] headerLines, Dictionary<string, List<string>> individuals, string[] footerLines) TestStatic_GetIndividuals(string gedCOMFile) => (string[] headerLines, Dictionary<string, List<string>> individuals, string[] footerLines) TestStatic_GetIndividuals(string? gedCOMFile) =>
GetIndividuals(gedCOMFile); GetIndividuals(gedCOMFile);
static (string[] headerLines, Dictionary<string, List<string>> individuals, string[] footerLines) GetIndividuals(string gedCOMFile) => static (string[] headerLines, Dictionary<string, List<string>> individuals, string[] footerLines) GetIndividuals(string? gedCOMFile) =>
Person.GetIndividuals(gedCOMFile); Person.GetIndividuals(gedCOMFile);
string[] TestStatic_GetFiltered(List<string> individualsLines) => string[] TestStatic_GetFiltered(List<string> individualsLines) =>

View File

@ -28,6 +28,11 @@ public interface IPersonBirthday
static Models.PersonBirthday GetPersonBirthday(long ticks) => static Models.PersonBirthday GetPersonBirthday(long ticks) =>
new(new(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) => string TestStatic_GetFileName(string personBirthdayFormat, Models.PersonBirthday personBirthday) =>
GetFileName(personBirthdayFormat, personBirthday); GetFileName(personBirthdayFormat, personBirthday);
static string GetFileName(string personBirthdayFormat, Models.PersonBirthday personBirthday) => static string GetFileName(string personBirthdayFormat, Models.PersonBirthday personBirthday) =>

View File

@ -5,10 +5,10 @@ public interface IPersonContainer
// ... // ...
Models.PersonContainer[] TestStatic_GetPersonContainers(Properties.IStorage storage, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, Dictionary<string, List<string>> individuals) => Models.PersonContainer[] TestStatic_GetPersonContainers(Properties.IStorage storage, string mappingDefaultName, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, Dictionary<string, List<string>> individuals) =>
GetPersonContainers(storage, personBirthdayFormat, personCharacters, facesFileNameExtension, individuals); GetPersonContainers(storage, mappingDefaultName, personBirthdayFormat, personCharacters, facesFileNameExtension, individuals);
static Models.PersonContainer[] GetPersonContainers(Properties.IStorage storage, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, Dictionary<string, List<string>> individuals) => static Models.PersonContainer[] GetPersonContainers(Properties.IStorage storage, string mappingDefaultName, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, Dictionary<string, List<string>> individuals) =>
PersonContainer.GetPersonContainers(storage, personBirthdayFormat, personCharacters, facesFileNameExtension, individuals); PersonContainer.GetPersonContainers(storage, mappingDefaultName, personBirthdayFormat, personCharacters, facesFileNameExtension, individuals);
List<(long?, string)> TestStatic_GetDisplay(string personBirthdayFormat, Models.PersonContainer personContainer) => List<(long?, string)> TestStatic_GetDisplay(string personBirthdayFormat, Models.PersonContainer personContainer) =>
GetDisplay(personBirthdayFormat, personContainer); GetDisplay(personBirthdayFormat, personContainer);

View File

@ -1,3 +1,5 @@
using System.Text.Json;
namespace View_by_Distance.Shared.Models.Stateless.Methods; namespace View_by_Distance.Shared.Models.Stateless.Methods;
internal abstract class Person internal abstract class Person
@ -49,19 +51,20 @@ internal abstract class Person
File.WriteAllLines(exportFile, cleanLines); File.WriteAllLines(exportFile, cleanLines);
} }
internal static (string[] headerLines, Dictionary<string, List<string>> individuals, string[] footerLines) GetIndividuals(string gedCOMFile) internal static (string[] headerLines, Dictionary<string, List<string>> individuals, string[] footerLines) GetIndividuals(string? gedCOMFile)
{ {
Dictionary<string, List<string>> results = new(); Dictionary<string, List<string>> results = new();
string? nick; string? nick;
int startAt = 0; int startAt = 0;
List<string> lines = new(); List<string> lines = new();
const string startsWith = "0 @";
List<string> headerLines = new(); List<string> headerLines = new();
List<string> footerLines = new(); List<string> footerLines = new();
string[] sourceLines = File.ReadAllLines(gedCOMFile); string[] sourceLines = string.IsNullOrEmpty(gedCOMFile) ? Array.Empty<string>() : File.ReadAllLines(gedCOMFile);
for (int i = 0; i < sourceLines.Length; i++) for (int i = 0; i < sourceLines.Length; i++)
{ {
lines.Add(sourceLines[i]); lines.Add(sourceLines[i]);
if (sourceLines[i].EndsWith("@ INDI")) if (sourceLines[i].StartsWith(startsWith))
{ {
lines.RemoveAt(lines.Count - 1); lines.RemoveAt(lines.Count - 1);
headerLines.AddRange(lines); headerLines.AddRange(lines);
@ -72,41 +75,44 @@ internal abstract class Person
} }
for (int i = startAt; i < sourceLines.Length; i++) for (int i = startAt; i < sourceLines.Length; i++)
{ {
if (!sourceLines[i].StartsWith("0 @")) if (!sourceLines[i].StartsWith(startsWith))
continue; continue;
nick = null; nick = null;
lines.Add(sourceLines[i]); lines.Add(sourceLines[i]);
for (int j = i + 1; j < sourceLines.Length; j++) if (sourceLines[i].EndsWith("@ FAM"))
{ {
if (sourceLines[j].StartsWith("0 @I")) for (int j = i + 1; j < sourceLines.Length; j++)
break; lines.Add(sourceLines[j]);
lines.Add(sourceLines[j]); footerLines.AddRange(lines);
if (!sourceLines[j].StartsWith("2 NICK ")) break;
continue;
nick = sourceLines[j][7..];
} }
if (string.IsNullOrEmpty(nick)) else if (sourceLines[i].EndsWith("@ INDI"))
{ {
if (lines[^1] != "0 TRLR") for (int j = i + 1; j < sourceLines.Length; j++)
throw new Exception(string.Join(Environment.NewLine, lines));
else
{ {
footerLines.AddRange(lines); if (sourceLines[j].StartsWith(startsWith))
break; 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()); else
results[nick].AddRange(lines); throw new NotSupportedException();
lines.Clear();
} }
return (headerLines.ToArray(), results, footerLines.ToArray()); 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? sexLine;
string? deathLine = null; string? deathLine = null;
string jrOrSr; string jrOrSr;
@ -115,13 +121,13 @@ internal abstract class Person
else else
{ {
if (name.Alias.Value.Contains(" Jr")) if (name.Alias.Value.Contains(" Jr"))
jrOrSr = "Jr"; jrOrSr = " Jr";
else if (name.Alias.Value.Contains(" Sr")) else if (name.Alias.Value.Contains(" Sr"))
jrOrSr = "Sr"; jrOrSr = " Sr";
else else
jrOrSr = string.Empty; 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") if (personKeyFormatted[^2..] is "23" or "21" or "19" or "17" or "15")
{ {
sexLine = "1 SEX M"; sexLine = "1 SEX M";
@ -160,18 +166,18 @@ internal abstract class Person
sexLine = "1 SEX U"; sexLine = "1 SEX U";
else else
{ {
string sex; string code;
if (deathLine is null or not "1 DEAT Y") 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 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")) if (directory.EndsWith("00"))
directory = string.Concat(directory[..^2], sex); directory = string.Concat(directory[..^2], code);
else if (directory.EndsWith("01")) else if (directory.EndsWith("01"))
directory = string.Concat(directory[..^2], sex); directory = string.Concat(directory[..^2], code);
else else
throw new NotImplementedException(); throw new NotImplementedException();
personKeyFormatted = $"{personKeyFormatted[..^2]}{sex}"; personKeyFormatted = $"{personKeyFormatted[..^2]}{code}";
} }
} }
List<string> pGedLines = new(); List<string> pGedLines = new();
@ -197,6 +203,8 @@ internal abstract class Person
pGedLines.Add("1 BIRT"); pGedLines.Add("1 BIRT");
pGedLines.Add($"2 DATE {personBirthday.Value:dd MMM yyyy}"); pGedLines.Add($"2 DATE {personBirthday.Value:dd MMM yyyy}");
} }
if (isDefaultName)
pGedLines.Add("9 NOTE");
if (filteredIndividualsLines is not null) if (filteredIndividualsLines is not null)
{ {
for (int i = 1; i < filteredIndividualsLines.Length; i++) 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()) if (personContainer.Key is null || personContainer.Birthdays is null || personContainer.Person is null || !personContainer.Birthdays.Any())
continue; continue;
if (personContainer.DisplayDirectoryName == mappingDefaultName || personContainer.Person.Name.Alias.Value == "Z") if (IPerson.IsDefaultName(mappingDefaultName, personContainer.DisplayDirectoryName) || IPerson.IsDefaultName(mappingDefaultName, personContainer.Person))
continue; continue;
if (distinct.Contains(personContainer.Key.Value)) if (distinct.Contains(personContainer.Key.Value))
continue; continue;
distinct.Add(personContainer.Key.Value); distinct.Add(personContainer.Key.Value);
if (!personKeyToIds.ContainsKey(personContainer.Key.Value))
continue;
personBirthday = personContainer.Birthdays[zero]; personBirthday = personContainer.Birthdays[zero];
personKeyFormatted = IPersonBirthday.GetFormatted(personBirthdayFormat, personBirthday); personKeyFormatted = IPersonBirthday.GetFormatted(personBirthdayFormat, personBirthday);
by = IPersonBirthday.IsCounterPersonBirthday(personBirthday) ? resultAllInOne : "People"; by = IPersonBirthday.IsCounterPersonBirthday(personBirthday) ? resultAllInOne : "People";
@ -275,6 +281,8 @@ internal abstract class Person
continue; continue;
pGedLines = File.ReadAllLines(pGedFiles[0]); pGedLines = File.ReadAllLines(pGedFiles[0]);
lines.AddRange(pGedLines); lines.AddRange(pGedLines);
if (!personKeyToIds.ContainsKey(personContainer.Key.Value))
lines.Add("1 NOTE");
// segments = personContainer.DisplayDirectoryName.Split(_Configuration.PersonCharacters.ToArray()); // segments = personContainer.DisplayDirectoryName.Split(_Configuration.PersonCharacters.ToArray());
// if (segments.Length < 2) // if (segments.Length < 2)
// directory = Path.Combine(rootDirectory, $"000 {personKeyFormatted} {personContainer.DisplayDirectoryName}"); // directory = Path.Combine(rootDirectory, $"000 {personKeyFormatted} {personContainer.DisplayDirectoryName}");
@ -288,9 +296,10 @@ internal abstract class Person
File.WriteAllLines(Path.Combine(a2PeopleContentDirectory, $"{ticks}.ged"), lines); 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; Models.Person result;
string[] matches;
const int zero = 0; const int zero = 0;
List<Models.PersonURL> urls = new(); List<Models.PersonURL> urls = new();
Models.PersonId id = new(personKey); Models.PersonId id = new(personKey);
@ -298,10 +307,29 @@ internal abstract class Person
List<Models.PersonNumber> numbers = new(); List<Models.PersonNumber> numbers = new();
List<Models.PersonComment> comments = new(); List<Models.PersonComment> comments = new();
List<Models.PersonAddress> addresses = new(); List<Models.PersonAddress> addresses = new();
Models.PersonName name = PersonName.Create(segments[zero]); string checkFileName = $"{personDisplayDirectoryName[zero]}.json";
string[] matches = (from l in personDisplayDirectoryAllFiles where !string.IsNullOrEmpty(personKeyFormatted) && l.Contains(personKeyFormatted) select l).ToArray(); 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<Models.PersonName>(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()) 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); result = new(id, personBirthday, name, comments, urls, numbers, emails, addresses);
return result; return result;
} }

View File

@ -132,4 +132,77 @@ internal abstract class PersonBirthday
return results; 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;
}
} }

View File

@ -3,41 +3,96 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods;
internal abstract class PersonContainer internal abstract class PersonContainer
{ {
private static string[] GetFiles(string personDisplayDirectory)
{
List<string> results = new();
string[] files;
string extension;
string checkFile;
string directoryName;
List<string> 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) private static string[] GetFiles(string facesFileNameExtension, string personDisplayDirectory)
{ {
string[] results = Directory.GetFiles(personDisplayDirectory, "*", SearchOption.TopDirectoryOnly); string[] results;
int? id; int? id;
string checkFile; string checkFile;
string? checkDirectory; string? checkDirectory;
int? normalizedRectangle; 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; continue;
(id, normalizedRectangle) = IMapping.GetConverted(facesFileNameExtension, personDisplayDirectoryAllFile); (id, normalizedRectangle) = IMapping.GetConverted(facesFileNameExtension, file);
if (id is not null && normalizedRectangle is not null) if (id is not null && normalizedRectangle is not null)
continue; continue;
checkDirectory = Path.GetDirectoryName(personDisplayDirectoryAllFile); checkDirectory = Path.GetDirectoryName(file);
if (string.IsNullOrEmpty(checkDirectory)) if (string.IsNullOrEmpty(checkDirectory))
continue; continue;
checkDirectory = Path.Combine(checkDirectory, "_ Invalid"); checkDirectory = Path.Combine(checkDirectory, "_ Invalid");
if (!Directory.Exists(checkDirectory)) if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory); _ = Directory.CreateDirectory(checkDirectory);
checkFile = Path.Combine(checkDirectory, Path.GetFileName(personDisplayDirectoryAllFile)); checkFile = Path.Combine(checkDirectory, Path.GetFileName(file));
if (File.Exists(checkFile)) if (File.Exists(checkFile))
File.Delete(personDisplayDirectoryAllFile); File.Delete(file);
else else
File.Move(personDisplayDirectoryAllFile, checkFile); File.Move(file, checkFile);
} }
results = Directory.GetFiles(personDisplayDirectory, "*", SearchOption.AllDirectories); results = GetFiles(personDisplayDirectory);
return results; return results;
} }
private static List<(long?, Models.PersonContainer)> GetPersonContainersCollections(string facesFileNameExtension, char[] personCharacters, Dictionary<string, List<string>> 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<string, List<string>> individuals, char @char, char numberSign, string personDisplayDirectory, string personDisplayDirectoryName, int? approximateYears, List<(string PersonKeyFormatted, Models.PersonBirthday PersonBirthday)> collection)
{ {
List<(long?, Models.PersonContainer)> results = new(); List<(long?, Models.PersonContainer)> results = new();
long personKey; long personKey;
string[] segments;
const int zero = 0; const int zero = 0;
Models.Person person; Models.Person person;
List<string>? individualsLines; List<string>? individualsLines;
@ -47,7 +102,6 @@ internal abstract class PersonContainer
string[] personDisplayDirectoryAllFiles = GetFiles(facesFileNameExtension, personDisplayDirectory); string[] personDisplayDirectoryAllFiles = GetFiles(facesFileNameExtension, personDisplayDirectory);
foreach ((string personKeyFormatted, Models.PersonBirthday personBirthday) in collection) 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(); orderedPersonBirthdays = (from l in collection where !l.PersonKeyFormatted.Contains(numberSign) orderby l.PersonBirthday.Value.Ticks descending select l.PersonBirthday).ToArray();
if (!orderedPersonBirthdays.Any()) if (!orderedPersonBirthdays.Any())
personKey = collection[zero].PersonBirthday.Value.Ticks; personKey = collection[zero].PersonBirthday.Value.Ticks;
@ -59,7 +113,7 @@ internal abstract class PersonContainer
} }
_ = individuals.TryGetValue(personKeyFormatted, out individualsLines); _ = individuals.TryGetValue(personKeyFormatted, out individualsLines);
filteredIndividualsLines = individualsLines is null ? null : IPerson.GetFiltered(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); personContainer = new(approximateYears, @char, person, orderedPersonBirthdays, personDisplayDirectoryAllFiles, personDisplayDirectoryName, personKey, filteredIndividualsLines);
results.Add(new(personKey, personContainer)); results.Add(new(personKey, personContainer));
} }
@ -105,7 +159,7 @@ internal abstract class PersonContainer
return result; return result;
} }
private static List<(long?, Models.PersonContainer)> GetPersonContainersGroup(string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, Dictionary<string, List<string>> individuals, char @char, string[] personDisplayDirectories) private static List<(long?, Models.PersonContainer)> GetPersonContainersGroup(string mappingDefaultName, string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, Dictionary<string, List<string>> individuals, char @char, string[] personDisplayDirectories)
{ {
List<(long?, Models.PersonContainer)> results = new(); List<(long?, Models.PersonContainer)> results = new();
string? minusOne; string? minusOne;
@ -134,7 +188,7 @@ internal abstract class PersonContainer
if (changes.Any(l => l is not null)) if (changes.Any(l => l is not null))
continue; continue;
if (collection.Any()) 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 else
{ {
personContainer = GetPersonContainer(facesFileNameExtension, @char, personDisplayDirectory, personDisplayDirectoryName, approximateYears); personContainer = GetPersonContainer(facesFileNameExtension, @char, personDisplayDirectory, personDisplayDirectoryName, approximateYears);
@ -146,7 +200,7 @@ internal abstract class PersonContainer
return results; return results;
} }
private static Models.PersonContainer[] GetPersonContainersGroups(string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, Dictionary<string, List<string>> individuals, string[] groupDirectories) private static Models.PersonContainer[] GetPersonContainersGroups(string mappingDefaultName, string personBirthdayFormat, string facesFileNameExtension, char[] personCharacters, Dictionary<string, List<string>> individuals, string[] groupDirectories)
{ {
Models.PersonContainer[] results; Models.PersonContainer[] results;
const int zero = 0; const int zero = 0;
@ -160,14 +214,14 @@ internal abstract class PersonContainer
if (!personCharacters.Contains(groupDirectoryName[zero])) if (!personCharacters.Contains(groupDirectoryName[zero]))
continue; continue;
personDisplayDirectories = Directory.GetDirectories(groupDirectory, "*", SearchOption.TopDirectoryOnly); 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); personContainers.AddRange(collection);
} }
results = (from l in personContainers orderby l.PersonKey is not null, l.PersonKey select l.PersonContainer).ToArray(); results = (from l in personContainers orderby l.PersonKey is not null, l.PersonKey select l.PersonContainer).ToArray();
return results; return results;
} }
internal static Models.PersonContainer[] GetPersonContainers(Properties.IStorage storage, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, Dictionary<string, List<string>> individuals) internal static Models.PersonContainer[] GetPersonContainers(Properties.IStorage storage, string mappingDefaultName, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, Dictionary<string, List<string>> individuals)
{ {
Models.PersonContainer[] results; Models.PersonContainer[] results;
string a2PeopleSingletonDirectory = Path.Combine(storage.PeopleRootDirectory, "{}"); string a2PeopleSingletonDirectory = Path.Combine(storage.PeopleRootDirectory, "{}");
@ -184,7 +238,7 @@ internal abstract class PersonContainer
if (!groupDirectories.Any()) if (!groupDirectories.Any())
results = Array.Empty<Models.PersonContainer>(); results = Array.Empty<Models.PersonContainer>();
else else
results = GetPersonContainersGroups(personBirthdayFormat, facesFileNameExtension, personCharacters, individuals, groupDirectories); results = GetPersonContainersGroups(mappingDefaultName, personBirthdayFormat, facesFileNameExtension, personCharacters, individuals, groupDirectories);
return results; return results;
} }
@ -205,5 +259,5 @@ internal abstract class PersonContainer
} }
return results; return results;
} }
} }

View File

@ -35,6 +35,7 @@ internal abstract partial class XDirectory
fileSearchFilter = string.Concat('*', fileSearchFilter); fileSearchFilter = string.Concat('*', fileSearchFilter);
if (!directorySearchFilter.Contains('*')) if (!directorySearchFilter.Contains('*'))
directorySearchFilter = string.Concat('*', directorySearchFilter); directorySearchFilter = string.Concat('*', directorySearchFilter);
results.Add(Directory.GetFiles(directory, fileSearchFilter, SearchOption.TopDirectoryOnly));
string[] directories = Directory.GetDirectories(directory, directorySearchFilter, SearchOption.TopDirectoryOnly); string[] directories = Directory.GetDirectories(directory, directorySearchFilter, SearchOption.TopDirectoryOnly);
foreach (string innerDirectory in directories) foreach (string innerDirectory in directories)
results.Add(Directory.GetFiles(innerDirectory, fileSearchFilter, SearchOption.AllDirectories)); results.Add(Directory.GetFiles(innerDirectory, fileSearchFilter, SearchOption.AllDirectories));

View File

@ -3,7 +3,7 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<LangVersion>10.0</LangVersion> <LangVersion>10.0</LangVersion>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifiers>win-x64;linux-x64</RuntimeIdentifiers>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>

View File

@ -61,6 +61,13 @@ public partial class UnitTestCalculations
_PropertyConfiguration = propertyConfiguration; _PropertyConfiguration = propertyConfiguration;
} }
private static void NonThrowTryCatch()
{
try
{ throw new Exception(); }
catch (Exception) { }
}
[TestMethod] [TestMethod]
public void TestMethodNull() public void TestMethodNull()
{ {
@ -71,6 +78,7 @@ public partial class UnitTestCalculations
Assert.IsFalse(_WorkingDirectory is null); Assert.IsFalse(_WorkingDirectory is null);
Assert.IsFalse(_ConfigurationRoot is null); Assert.IsFalse(_ConfigurationRoot is null);
Assert.IsFalse(_PropertyConfiguration is null); Assert.IsFalse(_PropertyConfiguration is null);
NonThrowTryCatch();
} }
[TestMethod] [TestMethod]
@ -87,29 +95,6 @@ public partial class UnitTestCalculations
Assert.IsTrue(age.Value > 42.6092); 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] [TestMethod]
public void TestMethodParse() public void TestMethodParse()
{ {
@ -138,52 +123,6 @@ public partial class UnitTestCalculations
Assert.IsTrue(successful == "_ Manual Copy Successful"); 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] [TestMethod]
public void TestMethodDirectory() public void TestMethodDirectory()
{ {
@ -302,71 +241,6 @@ public partial class UnitTestCalculations
Assert.IsTrue(distance == 1.4142135623730951); 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<string>();
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] [TestMethod]
public void TestGetConfidencePercent() public void TestGetConfidencePercent()
{ {
@ -426,6 +300,23 @@ public partial class UnitTestCalculations
File.Move(file, checkFile); 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();
} }
} }

247
Tests/UnitTestHardCoded.cs Normal file
View File

@ -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<UnitTestHardCoded>();
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<string>();
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();
}
}

View File

@ -49,6 +49,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "View-by-Distance.Shared", "
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Move-By-Id", "Move-By-Id\Move-By-Id.csproj", "{0FDFBC71-3801-483F-A4AC-CC8CF857D54F}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Move-By-Id", "Move-By-Id\Move-By-Id.csproj", "{0FDFBC71-3801-483F-A4AC-CC8CF857D54F}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Person", "Person\Person.csproj", "{C5003A39-334B-444B-9873-39B26E58D667}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU 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}.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.ActiveCfg = Release|Any CPU
{0FDFBC71-3801-483F-A4AC-CC8CF857D54F}.Release|Any CPU.Build.0 = 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 EndGlobalSection
EndGlobal EndGlobal