2023-02-11

This commit is contained in:
Mike Phares 2023-02-11 17:19:24 -07:00
parent 0b8df86e6b
commit 3d5c5952b3
13 changed files with 180 additions and 223 deletions

View File

@ -40,5 +40,6 @@
"files.exclude": {
"**/.git": false
},
"coverage-gutters.coverageBaseDir": "./.vscode/ReportGenerator/Cobertura/*"
"coverage-gutters.coverageBaseDir": "./.vscode/ReportGenerator/Cobertura/*",
"extensions.ignoreRecommendations": true
}

View File

@ -1,9 +1,7 @@
using ShellProgressBar;
using System.Text.Json;
using View_by_Distance.FaceRecognitionDotNet;
using View_by_Distance.Map.Models;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Properties;
namespace View_by_Distance.Distance.Models;
@ -15,19 +13,38 @@ public class MapLogicSupport : Shared.Models.Methods.IMapLogicSupport
private int _Distance;
private int _Confidence;
private readonly int _FaceConfidencePercent;
private readonly int _FaceDistancePermyriad;
private readonly int[] _RangeDaysDeltaTolerance;
private readonly int[] _RangeFaceAreaPermilleTolerance;
private readonly double _FaceAreaPermille;
private readonly double _RangeDaysDeltaTolerance;
private readonly double _FaceConfidencePercent;
private readonly double _FaceDistancePermyriad;
private readonly int _SortingMaximumPerFaceShouldBeHigh;
private readonly bool _RangeDaysDeltaTargetLessThenUpper;
public MapLogicSupport(int faceConfidencePercent, int faceDistancePermyriad, int[] rangeDaysDeltaTolerance, int[] rangeFaceAreaPermilleTolerance, int sortingMaximumPerFaceShouldBeHigh)
public MapLogicSupport(int faceConfidencePercent,
int faceDistancePermyriad,
int[] rangeDaysDeltaTolerance,
double[] rangeDistanceTolerance,
int[] rangeFaceAreaPermilleTolerance,
double[] rangeFaceConfidence,
int sortingMaximumPerFaceShouldBeHigh,
int? useFiltersCounter = null)
{
_FaceConfidencePercent = faceConfidencePercent;
_FaceDistancePermyriad = faceDistancePermyriad;
_RangeDaysDeltaTolerance = rangeDaysDeltaTolerance;
_RangeFaceAreaPermilleTolerance = rangeFaceAreaPermilleTolerance;
_SortingMaximumPerFaceShouldBeHigh = sortingMaximumPerFaceShouldBeHigh;
_RangeDaysDeltaTargetLessThenUpper = rangeDaysDeltaTolerance[1] > rangeDaysDeltaTolerance[2];
if (useFiltersCounter is null)
{
_FaceAreaPermille = rangeFaceAreaPermilleTolerance[1];
_RangeDaysDeltaTolerance = rangeDaysDeltaTolerance[1];
_FaceConfidencePercent = faceConfidencePercent * rangeFaceConfidence[1];
_FaceDistancePermyriad = faceDistancePermyriad * rangeDistanceTolerance[1];
}
else
{
_RangeDaysDeltaTolerance = ((rangeDaysDeltaTolerance[2] - rangeDaysDeltaTolerance[0]) * 0.01 * useFiltersCounter.Value) + rangeDaysDeltaTolerance[1];
_FaceConfidencePercent = faceConfidencePercent * ((rangeFaceConfidence[2] - rangeFaceConfidence[0]) * 0.01 * useFiltersCounter.Value) + rangeFaceConfidence[1];
_FaceAreaPermille = ((rangeFaceAreaPermilleTolerance[2] - rangeFaceAreaPermilleTolerance[0]) * 0.01 * useFiltersCounter.Value) + rangeFaceAreaPermilleTolerance[1];
_FaceDistancePermyriad = faceDistancePermyriad * ((rangeDistanceTolerance[2] - rangeDistanceTolerance[0]) * 0.01 * useFiltersCounter.Value) + rangeDistanceTolerance[1];
}
}
public static void SaveFaceDistances(Property.Models.Configuration configuration, SortingContainer[] sortingContainers)
@ -42,118 +59,33 @@ public class MapLogicSupport : Shared.Models.Methods.IMapLogicSupport
File.WriteAllLines(eDistanceContentFileName, results);
}
private List<SortingContainer> GetSortingContainers(Configuration mapConfiguration, Face face, FaceDistance faceDistanceEncoding, List<Sorting> sortingCollection, int? useFiltersCounter)
private List<SortingContainer> GetSortingContainers(Configuration mapConfiguration, Face face, FaceDistance faceDistanceEncoding, List<Sorting> sortingCollection)
{
List<SortingContainer> results = new();
SortingContainer sortingContainer;
Sorting[] collection = Shared.Models.Stateless.Methods.ISorting.Sort(sortingCollection);
double a;
double b;
double c;
double d;
double faceAreaPermille;
double faceConfidencePercent;
double faceDistancePermyriad;
double rangeDaysDeltaTolerance;
if (useFiltersCounter is null)
{
a = 1f;
b = 1f;
c = 1f;
d = 1f;
}
else if (useFiltersCounter.Value < 5)
{
a = 1.25f;
b = 0.8f;
c = a;
d = b;
}
else if (useFiltersCounter.Value < 9)
{
a = 1.5f;
b = 0.667f;
c = a;
d = b;
}
else if (useFiltersCounter.Value < 13)
{
a = 1.75f;
b = 0.571f;
c = a;
d = b;
}
else
{
a = 2f;
b = 0.5f;
c = a;
d = b;
}
if (useFiltersCounter is null)
{
rangeDaysDeltaTolerance = _RangeDaysDeltaTolerance[1];
faceDistancePermyriad = _FaceDistancePermyriad;
faceConfidencePercent = _FaceConfidencePercent;
faceAreaPermille = _RangeFaceAreaPermilleTolerance[1];
}
else if (useFiltersCounter.Value is 1 or 5 or 9 or 13)
{
rangeDaysDeltaTolerance = _RangeDaysDeltaTolerance[1] * a;
faceDistancePermyriad = _FaceDistancePermyriad * c;
faceConfidencePercent = _FaceConfidencePercent * d;
faceAreaPermille = _RangeFaceAreaPermilleTolerance[1] * d;
}
else if (useFiltersCounter.Value is 2 or 6 or 10 or 14)
{
rangeDaysDeltaTolerance = _RangeDaysDeltaTolerance[1] * c;
faceDistancePermyriad = _FaceDistancePermyriad * a;
faceConfidencePercent = _FaceConfidencePercent * d;
faceAreaPermille = _RangeFaceAreaPermilleTolerance[1] * d;
}
else if (useFiltersCounter.Value is 3 or 7 or 11 or 15)
{
rangeDaysDeltaTolerance = _RangeDaysDeltaTolerance[1] * c;
faceDistancePermyriad = _FaceDistancePermyriad * c;
faceConfidencePercent = _FaceConfidencePercent * b;
faceAreaPermille = _RangeFaceAreaPermilleTolerance[1] * d;
}
else if (useFiltersCounter.Value is 4 or 8 or 12 or 16)
{
rangeDaysDeltaTolerance = _RangeDaysDeltaTolerance[1] * c;
faceDistancePermyriad = _FaceDistancePermyriad * c;
faceConfidencePercent = _FaceConfidencePercent * d;
faceAreaPermille = _RangeFaceAreaPermilleTolerance[1] * b;
}
else
{
rangeDaysDeltaTolerance = int.MaxValue;
faceDistancePermyriad = int.MaxValue;
faceAreaPermille = 0;
faceConfidencePercent = 0;
}
foreach (Sorting sorting in collection)
{
if (face.Mapping is null || faceDistanceEncoding.NormalizedRectangle is null)
if (face.Mapping?.MappingFromLocation is null || faceDistanceEncoding.NormalizedRectangle is null)
throw new NotSupportedException();
if (!mapConfiguration.SaveSortingWithoutPerson && face.Mapping.MappingFromPerson is null)
continue;
if (sorting.DaysDelta > rangeDaysDeltaTolerance)
if (sorting.DaysDelta > _RangeDaysDeltaTolerance)
{
_Days += 1;
continue;
}
if (sorting.DistancePermyriad > faceDistancePermyriad)
if (sorting.DistancePermyriad > _FaceDistancePermyriad)
{
_Distance += 1;
continue;
}
if (face.Mapping.MappingFromLocation.ConfidencePercent < faceConfidencePercent)
if (face.Mapping.MappingFromLocation.ConfidencePercent < _FaceConfidencePercent)
{
_Confidence += 1;
continue;
}
if (face.Mapping.MappingFromLocation.AreaPermille < faceAreaPermille)
if (face.Mapping.MappingFromLocation.AreaPermille < _FaceAreaPermille)
{
_Area += 1;
continue;
@ -182,7 +114,7 @@ public class MapLogicSupport : Shared.Models.Methods.IMapLogicSupport
List<FaceDistanceContainer> collection = new();
foreach (Face face in distinctFilteredFaces)
{
if (face.Mapping is null)
if (face.Mapping?.MappingFromLocation is null)
throw new NotSupportedException();
if (face.FaceDistance?.Encoding is not FaceRecognitionDotNet.FaceEncoding faceEncoding)
continue;
@ -212,7 +144,7 @@ public class MapLogicSupport : Shared.Models.Methods.IMapLogicSupport
return faceDistanceEncodings;
}
public SortingContainer[] SetFaceMappingSortingCollectionThenGetSortingContainers(int maxDegreeOfParallelism, Configuration mapConfiguration, long ticks, MapLogic mapLogic, List<Face> distinctFilteredFaces, List<FaceDistanceContainer> missingFaceDistanceContainers, int? useFiltersCounter)
public SortingContainer[] SetFaceMappingSortingCollectionThenGetSortingContainers(int maxDegreeOfParallelism, Configuration mapConfiguration, long ticks, MapLogic mapLogic, List<Face> distinctFilteredFaces, List<FaceDistanceContainer> missingFaceDistanceContainers)
{
SortingContainer[] results;
List<SortingContainer> collection = new();
@ -235,7 +167,7 @@ public class MapLogicSupport : Shared.Models.Methods.IMapLogicSupport
List<Sorting> sortingCollection = GetSortingCollection(mapLogic, faceDistanceEncodings, i, faceDistanceEncoding);
if (!sortingCollection.Any())
return;
List<SortingContainer> sortingContainers = GetSortingContainers(mapConfiguration, face, faceDistanceEncoding, sortingCollection, useFiltersCounter);
List<SortingContainer> sortingContainers = GetSortingContainers(mapConfiguration, face, faceDistanceEncoding, sortingCollection);
if (sortingContainers.Any())
{
lock (collection)
@ -246,7 +178,7 @@ public class MapLogicSupport : Shared.Models.Methods.IMapLogicSupport
results = Array.Empty<SortingContainer>();
else
{
if (_RangeDaysDeltaTolerance[1] > _RangeDaysDeltaTolerance[2])
if (_RangeDaysDeltaTargetLessThenUpper)
results = Shared.Models.Stateless.Methods.ISortingContainer.Sort(collection);
else
results = Shared.Models.Stateless.Methods.ISortingContainer.SortUsingDaysDelta(collection);
@ -272,7 +204,7 @@ public class MapLogicSupport : Shared.Models.Methods.IMapLogicSupport
_ = Parallel.For(0, distinctFilteredFaces.Count, parallelOptions, (i, state) =>
{
Face face = distinctFilteredFaces[i];
if (face.FaceEncoding is null || face.Mapping is null)
if (face.FaceEncoding is null || face.Mapping?.MappingFromLocation is null)
throw new NotSupportedException();
if (face.FaceDistance?.Encoding is not null && face.FaceDistance.Encoding is FaceRecognitionDotNet.FaceEncoding faceEncoding)
return;
@ -284,62 +216,14 @@ public class MapLogicSupport : Shared.Models.Methods.IMapLogicSupport
});
}
void Shared.Models.Methods.IMapLogicSupport.SavePossiblyNewPersonContainers(IPropertyConfiguration propertyConfiguration, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, string? a2PeopleSingletonDirectory, Dictionary<long, PersonContainer> personKeyToPersonContainer, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer)
{
string json;
string[] files;
string checkFile;
string[] segments;
const int zero = 0;
char personCharacter;
string personKeyFormatted;
string personDisplayDirectory;
PersonBirthday personBirthday;
string personDisplayDirectoryName;
string checkPersonDisplayDirectory;
string checkPersonKeyFormattedDirectory;
JsonSerializerOptions jsonSerializerOptions = new() { WriteIndented = true };
foreach ((string[] personDisplayDirectoryNames, PersonContainer personContainer) in possiblyNewPersonDisplayDirectoryNamesAndPersonContainer)
{
if (a2PeopleSingletonDirectory is null || personContainer.Key is null || personContainer.Birthdays is null || !personContainer.Birthdays.Any())
continue;
personBirthday = personContainer.Birthdays[zero];
personDisplayDirectoryName = personDisplayDirectoryNames[^1];
personDisplayDirectory = Path.Combine(personDisplayDirectoryNames);
personKeyFormatted = Shared.Models.Stateless.Methods.IPersonBirthday.GetFormatted(personBirthdayFormat, personBirthday);
segments = personDisplayDirectoryName.Split(personCharacters);
if (segments.Length != 2)
personCharacter = '_';
else
personCharacter = personDisplayDirectoryName[segments[zero].Length];
checkPersonDisplayDirectory = Path.Combine(a2PeopleSingletonDirectory, personCharacter.ToString(), personDisplayDirectoryName);
checkPersonKeyFormattedDirectory = Path.Combine(checkPersonDisplayDirectory, personKeyFormatted);
if (Directory.Exists(checkPersonKeyFormattedDirectory))
continue;
_ = Directory.CreateDirectory(checkPersonKeyFormattedDirectory);
checkFile = Path.Combine(checkPersonKeyFormattedDirectory, $"{personKeyFormatted}.json");
json = JsonSerializer.Serialize(personContainer.Person, jsonSerializerOptions);
_ = Shared.Models.Stateless.Methods.IPath.WriteAllText(checkFile, json, updateDateWhenMatches: false, compareBeforeWrite: true);
if (!Directory.Exists(personDisplayDirectory))
continue;
files = Directory.GetFiles(personDisplayDirectory, $"*{facesFileNameExtension}", SearchOption.TopDirectoryOnly);
foreach (string file in files)
{
checkFile = Path.Combine(checkPersonDisplayDirectory, Path.GetFileName(file));
if (File.Exists(checkFile))
continue;
File.Copy(files[0], checkFile);
break;
}
}
}
public static Dictionary<int, Dictionary<int, Mapping>> GetIdToNormalizedRectangleToFace(Mapping[] mappingCollection)
{
Dictionary<int, Dictionary<int, Mapping>> results = new();
Dictionary<int, Mapping>? keyValuePairs;
foreach (Mapping mapping in mappingCollection)
{
if (mapping.MappingFromLocation is null)
continue;
if (!results.TryGetValue(mapping.MappingFromItem.Id, out keyValuePairs))
{
results.Add(mapping.MappingFromItem.Id, new());

View File

@ -598,7 +598,7 @@ public partial class DlibDotNet
DateTime[] containerDateTimes;
string deterministicHashCodeKey;
MappingFromItem mappingFromItem;
MappingFromLocation mappingFromLocation;
MappingFromLocation? mappingFromLocation;
List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection;
foreach (Container container in containers)
{
@ -618,12 +618,15 @@ public partial class DlibDotNet
foreach (Shared.Models.Face face in item.Faces)
{
if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null)
continue;
confidencePercent = Shared.Models.Stateless.Methods.ILocation.GetConfidencePercent(_Configuration.FaceConfidencePercent, _Configuration.RangeFaceConfidence, face.Location.Confidence);
faceAreaPermille = Shared.Models.Stateless.Methods.IMapping.GetAreaPermille(_Configuration.FaceAreaPermille, face.Location, face.OutputResolution);
normalizedRectangle = Shared.Models.Stateless.Methods.ILocation.GetNormalizedRectangle(face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution);
deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution);
mappingFromLocation = new(faceAreaPermille, confidencePercent, deterministicHashCodeKey, normalizedRectangle);
mappingFromLocation = null;
else
{
confidencePercent = Shared.Models.Stateless.Methods.ILocation.GetConfidencePercent(_Configuration.FaceConfidencePercent, _Configuration.RangeFaceConfidence, face.Location.Confidence);
faceAreaPermille = Shared.Models.Stateless.Methods.IMapping.GetAreaPermille(_Configuration.FaceAreaPermille, face.Location, face.OutputResolution);
normalizedRectangle = Shared.Models.Stateless.Methods.ILocation.GetNormalizedRectangle(face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution);
deterministicHashCodeKey = Shared.Models.Stateless.Methods.IMapping.GetDeterministicHashCodeKey(item.Property.Id.Value, face.Location, Shared.Models.Stateless.ILocation.Digits, face.OutputResolution);
mappingFromLocation = new(faceAreaPermille, confidencePercent, deterministicHashCodeKey, normalizedRectangle);
}
if (!fileNameToCollection.TryGetValue(mappingFromItem.RelativePath[1..], out mappingFromPhotoPrismCollection))
mappingFromPhotoPrismCollection = null;
mapping = new(mappingFromItem, mappingFromLocation, mappingFromPhotoPrismCollection);
@ -695,7 +698,7 @@ public partial class DlibDotNet
return items;
}
private void MapLogic(string argZero, long ticks, Container[] containers, string a2PeopleSingletonDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, string fPhotoPrismContentDirectory, MapLogicSupport mapLogicSupport, MapLogic mapLogic, string outputResolution, Dictionary<long, List<int>> personKeyToIds, List<Shared.Models.Face> distinctFilteredFaces, Mapping[] mappingCollection, int totalNotMapped)
private void MapLogic(string argZero, long ticks, Container[] containers, string a2PeopleSingletonDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory, string fPhotoPrismContentDirectory, MapLogic mapLogic, string outputResolution, Dictionary<long, List<int>> personKeyToIds, List<Shared.Models.Face> distinctFilteredFaces, Mapping[] mappingCollection, int totalNotMapped)
{
int? useFiltersCounter = null;
SortingContainer[] sortingContainers;
@ -708,7 +711,7 @@ public partial class DlibDotNet
if (_Configuration.SaveShortcutsForOutputResolutions.Contains(outputResolution))
{
List<Item> filteredItems = GetItems(argZero, containers);
mapLogic.SaveShortcutsForOutputResolutionsDuringMapLogic(personKeyToIds, filteredItems, mappingCollection);
mapLogic.SaveShortcutsForOutputResolutionsDuringMapLogic(personKeyToIds, dFacesContentDirectory, filteredItems, mappingCollection);
}
if (_Configuration.PersonCharactersCopyCount > 0 && !string.IsNullOrEmpty(_Configuration.PersonCharacters))
mapLogic.CopyAtLeastOneMappedFiles(dFacesContentDirectory, a2PeopleSingletonDirectory, mappingCollection);
@ -717,16 +720,19 @@ public partial class DlibDotNet
mapLogic.SaveMapped(dFacesContentDirectory, d2FacePartsContentDirectory, personKeyToIds, mappingCollection, idToNormalizedRectangleToMapping, totalNotMapped);
if (_Configuration.SaveFaceDistancesForOutputResolutions.Contains(outputResolution))
{
MapLogicSupport mapLogicSupport;
MapLogicSupport.SetFaceDistances(_AppSettings.MaxDegreeOfParallelism, ticks, distinctFilteredFaces);
List<Shared.Models.Face> distinctFurtherFilteredFaces = mapLogic.GetFurtherFilterBySkipCollection(distinctFilteredFaces);
Dictionary<int, Dictionary<int, PersonContainer[]>> missingIdThenNormalizedRectangleToPersonContainers = mapLogic.GetMissing(idToNormalizedRectangleToMapping);
List<FaceDistanceContainer> missingFaceDistanceContainers = _Distance.GetMissingFaceDistanceContainer(_AppSettings.MaxDegreeOfParallelism, ticks, dFacesCollectionDirectory, missingIdThenNormalizedRectangleToPersonContainers);
sortingContainers = mapLogicSupport.SetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, _MapConfiguration, ticks, mapLogic, distinctFurtherFilteredFaces, missingFaceDistanceContainers, useFiltersCounter);
mapLogicSupport = new(_Configuration.FaceConfidencePercent, _Configuration.FaceDistancePermyriad, _Configuration.RangeDaysDeltaTolerance, _Configuration.RangeDistanceTolerance, _Configuration.RangeFaceAreaPermilleTolerance, _Configuration.RangeFaceConfidence, _Configuration.SortingMaximumPerFaceShouldBeHigh);
sortingContainers = mapLogicSupport.SetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, _MapConfiguration, ticks, mapLogic, distinctFurtherFilteredFaces, missingFaceDistanceContainers);
if (!sortingContainers.Any())
{
for (useFiltersCounter = 1; useFiltersCounter < 17; useFiltersCounter++)
{
sortingContainers = mapLogicSupport.SetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, _MapConfiguration, ticks, mapLogic, distinctFurtherFilteredFaces, missingFaceDistanceContainers, useFiltersCounter);
mapLogicSupport = new(_Configuration.FaceConfidencePercent, _Configuration.FaceDistancePermyriad, _Configuration.RangeDaysDeltaTolerance, _Configuration.RangeDistanceTolerance, _Configuration.RangeFaceAreaPermilleTolerance, _Configuration.RangeFaceConfidence, _Configuration.SortingMaximumPerFaceShouldBeHigh, useFiltersCounter);
sortingContainers = mapLogicSupport.SetFaceMappingSortingCollectionThenGetSortingContainers(_AppSettings.MaxDegreeOfParallelism, _MapConfiguration, ticks, mapLogic, distinctFurtherFilteredFaces, missingFaceDistanceContainers);
if (sortingContainers.Any())
break;
}
@ -734,7 +740,7 @@ public partial class DlibDotNet
MapLogicSupport.SaveFaceDistances(_Configuration.PropertyConfiguration, sortingContainers);
if (totalNotMapped > 0)
{
int updated = mapLogic.UpdateFromSortingContainers(sortingContainers);
int updated = mapLogic.UpdateFromSortingContainers(mapLogicSupport, sortingContainers);
List<SaveContainer> saveContainers = mapLogic.GetSaveContainers(dFacesContentDirectory, d2FacePartsContentDirectory, mappingCollection, idToNormalizedRectangleToMapping, useFiltersCounter, sortingContainers.Any());
mapLogic.SaveContainers(totalNotMapped, updated, saveContainers);
}
@ -1043,14 +1049,13 @@ public partial class DlibDotNet
propertyLogic = new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _Resize.FileNameExtension, _Configuration.Reverse, aResultsFullGroupDirectory);
}
containers = Shared.Models.Stateless.Methods.IContainer.SortContainers(_Configuration.PropertyConfiguration, _Configuration.IgnoreRelativePaths, _ArgZeroIsConfigurationRootDirectory, argZero, containers);
MapLogicSupport mapLogicSupport = new(_Configuration.FaceConfidencePercent, _Configuration.FaceDistancePermyriad, _Configuration.RangeDaysDeltaTolerance, _Configuration.RangeFaceAreaPermilleTolerance, _Configuration.SortingMaximumPerFaceShouldBeHigh);
MapLogic? mapLogic = _Configuration.DistanceMoveUnableToMatch ? null : new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, ticks, _PersonContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory, mapLogicSupport);
MapLogic? mapLogic = _Configuration.DistanceMoveUnableToMatch ? null : new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, ticks, _PersonContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory);
personKeyToIds = mapLogic is null ? new() : mapLogic.GetPersonKeyToIds();
fileNameToCollection = !Directory.Exists(fPhotoPrismSingletonDirectory) ? fileNameToCollection = new() : F_PhotoPrism.GetFileNameToCollection(fPhotoPrismSingletonDirectory);
Dictionary<int, List<LocationContainer<MetadataExtractor.Directory>>> idToLocationContainers = GetDictionary(ticks, a2PeopleContentDirectory, eDistanceContentDirectory);
FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, t, containers, propertyLogic, metadata, eDistanceContentDirectory, fileNameToCollection, idToLocationContainers);
_Distance.Clear();
mapLogic ??= new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, ticks, _PersonContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory, mapLogicSupport);
mapLogic ??= new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, ticks, _PersonContainers, a2PeopleSingletonDirectory, eDistanceContentDirectory);
SetMapping(fileNameToCollection, argZero, containers);
if (!personKeyToIds.Any())
personKeyToIds = mapLogic.GetPersonKeyToIds();
@ -1076,7 +1081,7 @@ public partial class DlibDotNet
&& outputResolution == _Configuration.OutputResolutions[0]
&& _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)
&& _Exceptions.Count == 0)
MapLogic(argZero, ticks, containers, a2PeopleSingletonDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, fPhotoPrismContentDirectory, mapLogicSupport, mapLogic, outputResolution, personKeyToIds, distinctFilteredFaces, mappingCollection, totalNotMapped);
MapLogic(argZero, ticks, containers, a2PeopleSingletonDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory, fPhotoPrismContentDirectory, mapLogic, outputResolution, personKeyToIds, distinctFilteredFaces, mappingCollection, totalNotMapped);
if (_Configuration.SaveRandomForOutputResolutions.Contains(outputResolution) && personKeyToIds.Any() && mappingCollection.Any())
_Random.Random(_Configuration.PropertyConfiguration, outputResolution, personKeyToIds, mappingCollection);
if (_IsEnvironment.Development)

View File

@ -55,15 +55,15 @@ public class Configuration
public bool PropertiesChangedForMetadata { init; get; }
public bool PropertiesChangedForResize { init; get; }
public int[] RangeDaysDeltaTolerance { init; get; }
public double[] RangeDistanceTolerance { init; get; }
public int[] RangeFaceAreaPermilleTolerance { init; get; }
public double[] RangeFaceConfidence { init; get; }
public double[] RangeDistanceTolerance { init; get; }
public bool Reverse { init; get; }
public string[] SaveFaceDistancesForOutputResolutions { init; get; }
public string[] SaveFaceLandmarkForOutputResolutions { init; get; }
public string[] SaveFilteredOriginalImagesFromJLinksForOutputResolutions { init; get; }
public bool SaveFullYearOfRandomFiles { init; get; }
public string[] SaveMappedForOutputResolutions { init; get; }
public string[] SaveFilteredOriginalImagesFromJLinksForOutputResolutions { init; get; }
public string[] SaveRandomForOutputResolutions { init; get; }
public bool SaveResizedSubfiles { init; get; }
public string[] SaveShortcutsForOutputResolutions { init; get; }

View File

@ -25,14 +25,12 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
private readonly int _MaxDegreeOfParallelism;
private readonly Configuration? _Configuration;
private readonly string _EDistanceContentTicksDirectory;
private readonly Shared.Models.Methods.IMapLogicSupport? _MapLogicSupport;
private readonly Shared.Models.Properties.IPropertyConfiguration _PropertyConfiguration;
public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, long ticks, PersonContainer[] personContainers, string a2PeopleSingletonDirectory, string eDistanceContentDirectory, Shared.Models.Methods.IMapLogicSupport? mapLogicSupport)
public MapLogic(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, long ticks, PersonContainer[] personContainers, string a2PeopleSingletonDirectory, string eDistanceContentDirectory)
{
_Ticks = ticks;
_Configuration = configuration;
_MapLogicSupport = mapLogicSupport;
_Log = Serilog.Log.ForContext<MapLogic>();
_PropertyConfiguration = propertyConfiguration;
_MaxDegreeOfParallelism = maxDegreeOfParallelism;
@ -60,16 +58,14 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
_ = Directory.CreateDirectory(eDistanceContentDirectory);
if (!Directory.Exists(eDistanceContentTicksDirectory))
_ = Directory.CreateDirectory(eDistanceContentTicksDirectory);
if (configuration is not null && mapLogicSupport is not null)
if (configuration is not null)
{
List<PersonContainer> personContainerCollection = new(personContainers);
Stateless.MapLogic.Set(propertyConfiguration,
configuration,
Stateless.MapLogic.Set(configuration,
ticks,
personContainerCollection,
a2PeopleSingletonDirectory,
eDistanceContentDirectory,
mapLogicSupport,
personKeyToPersonContainer,
notMappedPersonContainers,
skipCollection,
@ -185,6 +181,8 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
Dictionary<int, PersonContainer[]>? normalizedRectangleToPersonContainers;
foreach (Mapping mapping in mappingCollection)
{
if (mapping.MappingFromLocation is null)
continue;
if (!_IdThenNormalizedRectangleToPersonContainers.TryGetValue(mapping.MappingFromItem.Id, out normalizedRectangleToPersonContainers))
{
if (_SkipCollection.TryGetValue(mapping.MappingFromItem.Id, out normalizedRectangles) && normalizedRectangles.Contains(mapping.MappingFromLocation.NormalizedRectangle))
@ -335,7 +333,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
SaveContainer? result;
string shortcutFile = string.Empty;
string? facesDirectory = GetFacesDirectory(dFacesContentDirectory, mapping.MappingFromItem);
if (facesDirectory is null)
if (facesDirectory is null || mapping.MappingFromLocation is null)
result = null;
else
{
@ -446,6 +444,8 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
string forceSingleImageHumanized = nameof(Shared.Models.Stateless.IMapLogic.ForceSingleImage).Humanize(LetterCasing.Title);
foreach (Mapping mapping in mappingCollection)
{
if (mapping.MappingFromLocation is null)
continue;
directoryName = Path.GetDirectoryName(mapping.MappingFromItem.RelativePath);
if (directoryName is null)
throw new NotSupportedException();
@ -462,7 +462,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
{
if (sortingContainersAny)
continue;
mapping.UpdateMappingFromUnknownPerson(new(mapping, new(mapping)));
mapping.UpdateMappingFromUnknownPerson(new(mapping, new(mapping, mapping.MappingFromLocation)));
if (mapping.SortingContainer is null)
continue;
}
@ -626,13 +626,13 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
return results;
}
public int UpdateFromSortingContainers(SortingContainer[] sortingContainers)
public int UpdateFromSortingContainers(Shared.Models.Methods.IMapLogicSupport mapLogicSupport, SortingContainer[] sortingContainers)
{
if (_Configuration is null)
throw new NullReferenceException(nameof(_Configuration));
if (_MapLogicSupport is not null)
if (mapLogicSupport is not null)
{
string counts = _MapLogicSupport.GetCounts();
string counts = mapLogicSupport.GetCounts();
_ = Directory.CreateDirectory(Path.Combine(_EDistanceContentTicksDirectory, counts));
}
int result = 0;
@ -656,7 +656,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
foreach (SortingContainer sortingContainer in sortingContainers)
{
progressBar.Tick();
if (sortingContainer.Mapping is null)
if (sortingContainer.Mapping?.MappingFromLocation is null)
throw new NotSupportedException();
if (!idToNormalizedRectangleCollectionForA.ContainsKey(sortingContainer.Mapping.MappingFromItem.Id))
idToNormalizedRectangleCollectionForA.Add(sortingContainer.Mapping.MappingFromItem.Id, new());
@ -761,6 +761,8 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
if (!normalizedRectangleToMapping.ContainsKey(normalizedRectangle.Value))
continue;
mapping = normalizedRectangleToMapping[normalizedRectangle.Value];
if (mapping.MappingFromLocation is null)
continue;
if (string.IsNullOrEmpty(personDisplayDirectory))
throw new NotSupportedException();
directoryName = Path.GetDirectoryName(mapping.MappingFromItem.RelativePath);
@ -822,7 +824,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
directoryName = Path.GetDirectoryName(mapping.MappingFromItem.RelativePath);
if (directoryName is null)
throw new NotSupportedException();
if (mapping.MappingFromPerson is null)
if (mapping.MappingFromLocation is null || mapping.MappingFromPerson is null)
continue;
if (mapping.MappingFromItem.ResizedFileHolder.DirectoryName is null || !mapping.MappingFromItem.ResizedFileHolder.Exists)
continue;
@ -903,8 +905,6 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
{
if (_Configuration is null)
throw new NullReferenceException(nameof(_Configuration));
if (_MapLogicSupport is null)
throw new NullReferenceException(nameof(_MapLogicSupport));
List<string> results = new();
string[] files;
string checkDirectory;
@ -979,7 +979,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
throw new NotSupportedException();
if (mapping.By is null or Shared.Models.Stateless.IMapLogic.Sorting)
continue;
if (mapping.MappingFromPerson?.ApproximateYears is null)
if (mapping.MappingFromPerson?.ApproximateYears is null || mapping.MappingFromLocation is null)
continue;
if (string.IsNullOrEmpty(mapping.MappingFromPerson.SegmentB))
throw new NotSupportedException();
@ -1097,7 +1097,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
Dictionary<int, List<long>> idToPersonKeys = Stateless.Methods.IMapLogic.GetIdToPersonKeys(personKeyToIds);
foreach (Mapping mapping in mappingCollection)
{
if (mapping.MappingFromItem.ImageFileHolder.DirectoryName is null || mapping.MappingFromPerson is null)
if (mapping.MappingFromLocation is null || mapping.MappingFromItem.ImageFileHolder.DirectoryName is null || mapping.MappingFromPerson is null)
continue;
if (!idToLocationContainers.TryGetValue(mapping.MappingFromItem.Id, out locationContainers) || !locationContainers.Any())
directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(mapping.MappingFromItem.ResizedFileHolder.FullName);
@ -1112,9 +1112,9 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
if (!string.IsNullOrEmpty(model) && !string.IsNullOrEmpty(model.Trim()))
{
model = Regex.Replace(model, @"[\\,\/,\:,\*,\?,\"",\<,\>,\|]", "_");
directory = Path.Combine(eDistanceContentDirectory, "Model Shortcuts", model, Path.GetFileName(mapping.MappingFromItem.ImageFileHolder.DirectoryName));
directory = Path.Combine($"{eDistanceContentDirectory}---", "Model Shortcuts", model, Path.GetFileName(mapping.MappingFromItem.ImageFileHolder.DirectoryName));
fileName = Path.Combine(directory, $"{mapping.MappingFromItem.ImageFileHolder.Name}.lnk");
results.Add(new(mapping.MappingFromItem.ImageFileHolder.FullName, directory, mapping.MappingFromItem.MinimumDateTime, fileName, mapping.MappingFromLocation.DeterministicHashCodeKey));
results.Add(new(mapping.MappingFromItem.ImageFileHolder.FullName, directory, mapping.MappingFromItem.MinimumDateTime, fileName, mapping.MappingFromLocation.DeterministicHashCodeKey, MakeAllHidden: false));
}
if (!idToPersonKeys.TryGetValue(mapping.MappingFromItem.Id, out personKeys))
continue;
@ -1122,12 +1122,12 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
if (!personKeys.Contains(mapping.MappingFromPerson.PersonBirthday.Value.Ticks))
continue;
personKeyFormatted = IPersonBirthday.GetFormatted(_Configuration.PersonBirthdayFormat, mapping.MappingFromPerson.PersonBirthday);
directory = Path.Combine(eDistanceContentDirectory, "Person Key Shortcuts", personKeyFormatted, Path.GetFileName(mapping.MappingFromItem.ImageFileHolder.DirectoryName));
directory = Path.Combine($"{eDistanceContentDirectory}---", "Person Key Shortcuts", personKeyFormatted, Path.GetFileName(mapping.MappingFromItem.ImageFileHolder.DirectoryName));
fileName = Path.Combine(directory, $"{mapping.MappingFromItem.ImageFileHolder.Name}.lnk");
results.Add(new(mapping.MappingFromItem.ImageFileHolder.FullName, directory, mapping.MappingFromItem.MinimumDateTime, fileName, mapping.MappingFromLocation.DeterministicHashCodeKey));
directory = Path.Combine(eDistanceContentDirectory, "Name Shortcuts", mapping.MappingFromPerson.DisplayDirectoryName, Path.GetFileName(mapping.MappingFromItem.ImageFileHolder.DirectoryName));
results.Add(new(mapping.MappingFromItem.ImageFileHolder.FullName, directory, mapping.MappingFromItem.MinimumDateTime, fileName, mapping.MappingFromLocation.DeterministicHashCodeKey, MakeAllHidden: false));
directory = Path.Combine($"{eDistanceContentDirectory}---", "Name Shortcuts", mapping.MappingFromPerson.DisplayDirectoryName, Path.GetFileName(mapping.MappingFromItem.ImageFileHolder.DirectoryName));
fileName = Path.Combine(directory, $"{mapping.MappingFromItem.ImageFileHolder.Name}.lnk");
results.Add(new(mapping.MappingFromItem.ImageFileHolder.FullName, directory, mapping.MappingFromItem.MinimumDateTime, fileName, mapping.MappingFromLocation.DeterministicHashCodeKey));
results.Add(new(mapping.MappingFromItem.ImageFileHolder.FullName, directory, mapping.MappingFromItem.MinimumDateTime, fileName, mapping.MappingFromLocation.DeterministicHashCodeKey, MakeAllHidden: false));
}
return results;
}
@ -1151,9 +1151,12 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
hiddenFile = $"{s.FileName}.lvs";
if (File.Exists(hiddenFile))
continue;
File.WriteAllLines(hiddenFile, new string[] { s.FullName, s.Description });
File.SetAttributes(hiddenFile, FileAttributes.Hidden);
File.SetLastWriteTime(hiddenFile, s.DateTime);
if (s.Description is not null)
{
File.WriteAllLines(hiddenFile, new string[] { s.FullName, s.Description });
File.SetAttributes(hiddenFile, FileAttributes.Hidden);
File.SetLastWriteTime(hiddenFile, s.DateTime);
}
if (File.Exists(s.FileName))
continue;
try
@ -1168,15 +1171,17 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
}
}
private (List<(string, DateTime[])>, List<SaveShortcutsForOutputResolutions>) GetCollectionForSaveShortcutsForOutputResolutionsDuringMapLogic(Dictionary<long, List<int>> personKeyToIds, List<Item> filteredItems, Mapping[] mappingCollection)
private (List<(string, DateTime[])>, List<SaveShortcutsForOutputResolutions>) GetCollectionForSaveShortcutsForOutputResolutionsDuringMapLogic(Dictionary<long, List<int>> personKeyToIds, string dFacesContentDirectory, List<Item> filteredItems, Mapping[] mappingCollection)
{
if (_Configuration is null)
throw new NullReferenceException(nameof(_Configuration));
long personKey;
string fileName;
string fullName;
string directory;
string? directoryName;
string personDirectory;
string? facesDirectory;
string personKeyFormatted;
List<string> distinct = new();
List<SaveShortcutsForOutputResolutions> collection = new();
@ -1185,9 +1190,11 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
{
if (item.ResizedFileHolder is null)
continue;
if (item.Faces.Any(l => l.FaceEncoding is not null))
continue;
foreach (Face face in item.Faces)
{
if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null || face.Mapping is null)
if (face.Mapping is null)
continue;
directoryName = Path.GetDirectoryName(face.Mapping.MappingFromItem.RelativePath);
if (directoryName is null)
@ -1197,7 +1204,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
directory = Path.Combine(item.ResizedFileHolder.DirectoryName, $"{_PropertyConfiguration.ResultAllInOne}Shortcuts", _PropertyConfiguration.ResultAllInOne);
personDirectory = Path.Combine(directory, "No Faces");
fileName = Path.Combine(personDirectory, $"{item.ResizedFileHolder.Name}.lnk");
collection.Add(new(item.ResizedFileHolder.FullName, personDirectory, item.ImageFileHolder.LastWriteTime.Value, fileName, face.Mapping.MappingFromItem.Id.ToString()));
collection.Add(new(item.ResizedFileHolder.FullName, personDirectory, item.ImageFileHolder.LastWriteTime.Value, fileName, face.Mapping.MappingFromItem.Id.ToString(), MakeAllHidden: false));
if (face.Mapping.MappingFromItem.ContainerDateTimes.Any() && !distinct.Contains(item.ResizedFileHolder.DirectoryName))
{
distinct.Add(item.ResizedFileHolder.DirectoryName);
@ -1222,7 +1229,13 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
directory = Path.Combine(mapping.MappingFromItem.ResizedFileHolder.DirectoryName, $"{_PropertyConfiguration.ResultAllInOne}Shortcuts", _PropertyConfiguration.ResultAllInOne);
personDirectory = Path.Combine(directory, "Unknown");
fileName = Path.Combine(personDirectory, $"{mapping.MappingFromItem.ResizedFileHolder.Name}.lnk");
collection.Add(new(mapping.MappingFromItem.ResizedFileHolder.FullName, personDirectory, mapping.MappingFromItem.MinimumDateTime, fileName, mapping.MappingFromLocation.DeterministicHashCodeKey));
collection.Add(new(mapping.MappingFromItem.ResizedFileHolder.FullName, personDirectory, mapping.MappingFromItem.MinimumDateTime, fileName, mapping.MappingFromLocation?.DeterministicHashCodeKey, MakeAllHidden: false));
facesDirectory = GetFacesDirectory(dFacesContentDirectory, mapping.MappingFromItem);
if (facesDirectory is null || mapping.MappingFromLocation is null)
continue;
fullName = Path.Combine(facesDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}{_Configuration.FacesFileNameExtension}");
fileName = Path.Combine(personDirectory, $"{mapping.MappingFromLocation.DeterministicHashCodeKey}{mapping.MappingFromItem.ResizedFileHolder.ExtensionLowered}{_Configuration.FacesFileNameExtension}.lnk");
collection.Add(new(fullName, personDirectory, mapping.MappingFromItem.MinimumDateTime, fileName, mapping.MappingFromLocation.DeterministicHashCodeKey, MakeAllHidden: true));
}
else
{
@ -1243,20 +1256,20 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
else
personDirectory = Path.Combine(directory, mapping.MappingFromPerson.DisplayDirectoryName, $"{personKeyToIds[personKey].Count} Face(s)");
fileName = Path.Combine(directory, $"{mapping.MappingFromItem.ResizedFileHolder.Name}.lnk");
collection.Add(new(mapping.MappingFromItem.ResizedFileHolder.FullName, personDirectory, mapping.MappingFromItem.MinimumDateTime, fileName, mapping.MappingFromLocation.DeterministicHashCodeKey));
collection.Add(new(mapping.MappingFromItem.ResizedFileHolder.FullName, personDirectory, mapping.MappingFromItem.MinimumDateTime, fileName, mapping.MappingFromLocation?.DeterministicHashCodeKey, MakeAllHidden: false));
}
}
return new(directoriesAndDateTimes, collection);
}
public void SaveShortcutsForOutputResolutionsDuringMapLogic(Dictionary<long, List<int>> personKeyToIds, List<Item> filteredItems, Mapping[] mappingCollection)
public void SaveShortcutsForOutputResolutionsDuringMapLogic(Dictionary<long, List<int>> personKeyToIds, string dFacesContentDirectory, List<Item> filteredItems, Mapping[] mappingCollection)
{
if (_Configuration is null)
throw new NullReferenceException(nameof(_Configuration));
WindowsShortcut windowsShortcut;
List<(string, DateTime[])> directoriesAndDateTimes;
List<SaveShortcutsForOutputResolutions> collection;
(directoriesAndDateTimes, collection) = GetCollectionForSaveShortcutsForOutputResolutionsDuringMapLogic(personKeyToIds, filteredItems, mappingCollection);
(directoriesAndDateTimes, collection) = GetCollectionForSaveShortcutsForOutputResolutionsDuringMapLogic(personKeyToIds, dFacesContentDirectory, filteredItems, mappingCollection);
string[] directories = (from l in collection select l.Directory).Distinct().ToArray();
foreach (string directory in directories)
{
@ -1274,6 +1287,8 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
windowsShortcut = new() { Path = s.FullName, Description = s.Description };
windowsShortcut.Save(s.FileName);
windowsShortcut.Dispose();
if (s.MakeAllHidden)
File.SetAttributes(s.FileName, FileAttributes.Hidden);
File.SetLastWriteTime(s.FileName, s.DateTime);
}
catch (Exception)
@ -1306,7 +1321,7 @@ public class MapLogic : Shared.Models.Methods.IMapLogic
List<int>? normalizedRectangles;
foreach (Face face in distinctFilteredFaces)
{
if (face.Mapping is null)
if (face.Mapping?.MappingFromLocation is null)
continue;
if (_SkipCollection.TryGetValue(face.Mapping.MappingFromItem.Id, out normalizedRectangles) && normalizedRectangles.Contains(face.Mapping.MappingFromLocation.NormalizedRectangle))
continue;

View File

@ -1,5 +1,6 @@
using Humanizer;
using ShellProgressBar;
using System.Text.Json;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Stateless.Methods;
using WindowsShortcutFactory;
@ -503,7 +504,57 @@ internal abstract class MapLogic
}
}
internal static void Set(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration? configuration, long ticks, List<PersonContainer> personContainers, string? a2PeopleContentDirectory, string eDistanceContentDirectory, Shared.Models.Methods.IMapLogicSupport mapLogicSupport, Dictionary<long, PersonContainer> personKeyToPersonContainer, List<PersonContainer> notMappedPersonContainers, Dictionary<int, List<int>> skipCollection, Dictionary<int, Dictionary<int, PersonContainer[]>> idThenNormalizedRectangleToPersonContainers)
static void SavePossiblyNewPersonContainers(string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, string? a2PeopleSingletonDirectory, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer)
{
string json;
string[] files;
string checkFile;
string[] segments;
const int zero = 0;
char personCharacter;
string personKeyFormatted;
string personDisplayDirectory;
PersonBirthday personBirthday;
string personDisplayDirectoryName;
string checkPersonDisplayDirectory;
string checkPersonKeyFormattedDirectory;
JsonSerializerOptions jsonSerializerOptions = new() { WriteIndented = true };
foreach ((string[] personDisplayDirectoryNames, PersonContainer personContainer) in possiblyNewPersonDisplayDirectoryNamesAndPersonContainer)
{
if (a2PeopleSingletonDirectory is null || personContainer.Key is null || personContainer.Birthdays is null || !personContainer.Birthdays.Any())
continue;
personBirthday = personContainer.Birthdays[zero];
personDisplayDirectoryName = personDisplayDirectoryNames[^1];
personDisplayDirectory = Path.Combine(personDisplayDirectoryNames);
personKeyFormatted = IPersonBirthday.GetFormatted(personBirthdayFormat, personBirthday);
segments = personDisplayDirectoryName.Split(personCharacters);
if (segments.Length != 2)
personCharacter = '_';
else
personCharacter = personDisplayDirectoryName[segments[zero].Length];
checkPersonDisplayDirectory = Path.Combine(a2PeopleSingletonDirectory, personCharacter.ToString(), personDisplayDirectoryName);
checkPersonKeyFormattedDirectory = Path.Combine(checkPersonDisplayDirectory, personKeyFormatted);
if (Directory.Exists(checkPersonKeyFormattedDirectory))
continue;
_ = Directory.CreateDirectory(checkPersonKeyFormattedDirectory);
checkFile = Path.Combine(checkPersonKeyFormattedDirectory, $"{personKeyFormatted}.json");
json = JsonSerializer.Serialize(personContainer.Person, jsonSerializerOptions);
_ = IPath.WriteAllText(checkFile, json, updateDateWhenMatches: false, compareBeforeWrite: true);
if (!Directory.Exists(personDisplayDirectory))
continue;
files = Directory.GetFiles(personDisplayDirectory, $"*{facesFileNameExtension}", SearchOption.TopDirectoryOnly);
foreach (string file in files)
{
checkFile = Path.Combine(checkPersonDisplayDirectory, Path.GetFileName(file));
if (File.Exists(checkFile))
continue;
File.Copy(files[0], checkFile);
break;
}
}
}
internal static void Set(Configuration? configuration, long ticks, List<PersonContainer> personContainers, string? a2PeopleContentDirectory, string eDistanceContentDirectory, Dictionary<long, PersonContainer> personKeyToPersonContainer, List<PersonContainer> notMappedPersonContainers, Dictionary<int, List<int>> skipCollection, Dictionary<int, Dictionary<int, PersonContainer[]>> idThenNormalizedRectangleToPersonContainers)
{
if (configuration is null)
throw new NullReferenceException(nameof(configuration));
@ -543,7 +594,7 @@ internal abstract class MapLogic
notMappedPersonContainers.AddRange(GetNotMappedPersonContainers(configuration, personContainers, personKeys, personKeyCollection));
AppendToSkipCollection(skipCollection, idThenNormalizedRectangleToPersonContainers, incorrectIdThenNormalizedRectangleToPersonContainers);
if (possiblyNewPersonDisplayDirectoryNamesAndPersonContainer.Any())
mapLogicSupport.SavePossiblyNewPersonContainers(propertyConfiguration, configuration.PersonBirthdayFormat, configuration.PersonCharacters.ToArray(), configuration.FacesFileNameExtension, a2PeopleContentDirectory, personKeyToPersonContainer, possiblyNewPersonDisplayDirectoryNamesAndPersonContainer);
SavePossiblyNewPersonContainers(configuration.PersonBirthdayFormat, configuration.PersonCharacters.ToArray(), configuration.FacesFileNameExtension, a2PeopleContentDirectory, possiblyNewPersonDisplayDirectoryNamesAndPersonContainer);
}
private static string GetMappingSegmentB(long ticks, PersonBirthday personBirthday, int? approximateYears, long minimumDateTimeTicks, bool? isWrongYear)
@ -587,6 +638,8 @@ internal abstract class MapLogic
internal static SaveContainer GetDebugSaveContainer(string directory, SortingContainer sortingContainer, Mapping mapping)
{
SaveContainer result;
if (sortingContainer.Mapping.MappingFromLocation is null)
throw new NullReferenceException(nameof(sortingContainer.Mapping.MappingFromLocation));
FileHolder faceFileHolder = new($"C:/{sortingContainer.Sorting.Id}.{sortingContainer.Sorting.NormalizedRectangle}");
string shortcutFile = Path.Combine(directory, $"{sortingContainer.Mapping.MappingFromLocation.DeterministicHashCodeKey}{sortingContainer.Mapping.MappingFromItem.ImageFileHolder.ExtensionLowered}.debug.lnk");
result = new(directory, faceFileHolder, mapping.MappingFromItem.ResizedFileHolder, shortcutFile);

View File

@ -109,7 +109,7 @@ public class F_PhotoPrism
foreach (Face face in distinctFilteredFaces)
{
collection.Clear();
normalizedRectangle = face.Mapping?.MappingFromLocation.NormalizedRectangle;
normalizedRectangle = face.Mapping?.MappingFromLocation?.NormalizedRectangle;
if (normalizedRectangle is null)
continue;
if (face.FaceEncoding is null || face.Location is null || face.OutputResolution is null || face.Mapping is null)

View File

@ -123,14 +123,14 @@ public class Mapping : Properties.IMapping
protected SortingContainer? _SortingContainer;
public int? By => _By;
public MappingFromItem MappingFromItem { init; get; }
public MappingFromLocation MappingFromLocation { init; get; }
public MappingFromLocation? MappingFromLocation { init; get; }
public List<MappingFromPhotoPrism>? MappingFromPhotoPrismCollection { init; get; }
public MappingFromPerson? MappingFromPerson => _MappingFromPerson;
public string? SegmentC => _SegmentC;
public SortingContainer? SortingContainer => _SortingContainer;
[JsonConstructor]
public Mapping(int? by, MappingFromItem mappingFromItem, MappingFromLocation mappingFromLocation, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection, MappingFromPerson? mappingFromPerson, string? segmentC, SortingContainer? sortingContainer)
public Mapping(int? by, MappingFromItem mappingFromItem, MappingFromLocation? mappingFromLocation, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection, MappingFromPerson? mappingFromPerson, string? segmentC, SortingContainer? sortingContainer)
{
_By = by;
_SegmentC = segmentC;
@ -141,7 +141,7 @@ public class Mapping : Properties.IMapping
_SortingContainer = sortingContainer;
}
public Mapping(MappingFromItem mappingFromItem, MappingFromLocation mappingFromLocation, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection) :
public Mapping(MappingFromItem mappingFromItem, MappingFromLocation? mappingFromLocation, List<MappingFromPhotoPrism>? mappingFromPhotoPrismCollection) :
this(null, mappingFromItem, mappingFromLocation, mappingFromPhotoPrismCollection, null, null, null)
{ }

View File

@ -4,6 +4,5 @@ public interface IMapLogicSupport
{
string GetCounts();
void SavePossiblyNewPersonContainers(Properties.IPropertyConfiguration propertyConfiguration, string personBirthdayFormat, char[] personCharacters, string facesFileNameExtension, string? a2PeopleContentDirectory, Dictionary<long, PersonContainer> personKeyToPersonContainer, List<(string[], PersonContainer)> possiblyNewPersonDisplayDirectoryNamesAndPersonContainer);
}

View File

@ -47,7 +47,7 @@ public interface IMapping
public int? By { get; }
public string? SegmentC { get; }
public MappingFromItem MappingFromItem { init; get; }
public MappingFromLocation MappingFromLocation { init; get; }
public MappingFromLocation? MappingFromLocation { init; get; }
public List<MappingFromPhotoPrism>? MappingFromPhotoPrismCollection { init; get; }
public MappingFromPerson? MappingFromPerson { get; }
public SortingContainer? SortingContainer { get; }

View File

@ -1,4 +1,4 @@
namespace View_by_Distance.Shared.Models;
public record SaveShortcutsForOutputResolutions(string FullName, string Directory, DateTime DateTime, string FileName, string Description)
public record SaveShortcutsForOutputResolutions(string FullName, string Directory, DateTime DateTime, string FileName, string? Description, bool MakeAllHidden)
{ }

View File

@ -22,8 +22,8 @@ public record class Sorting : Properties.ISorting
Older = older;
}
public Sorting(Mapping mapping) :
this(0, 0, mapping.MappingFromItem.Id, mapping.MappingFromLocation.NormalizedRectangle, false)
public Sorting(Mapping mapping, MappingFromLocation mappingFromLocation) :
this(0, 0, mapping.MappingFromItem.Id, mappingFromLocation.NormalizedRectangle, false)
{ }
public override string ToString()

View File

@ -17,7 +17,7 @@ public record class SortingContainer : Properties.ISortingContainer
public override string ToString()
{
string result = string.Concat(Mapping.MappingFromItem.Id, '\t', Mapping.MappingFromLocation.NormalizedRectangle, '\t', Sorting.Id, '\t', Sorting.NormalizedRectangle, '\t', Sorting.Older, '\t', '\t', Sorting.DistancePermyriad, '\t', Sorting.DaysDelta);
string result = string.Concat(Mapping.MappingFromItem.Id, '\t', Mapping.MappingFromLocation?.NormalizedRectangle, '\t', Sorting.Id, '\t', Sorting.NormalizedRectangle, '\t', Sorting.Older, '\t', '\t', Sorting.DistancePermyriad, '\t', Sorting.DaysDelta);
return result;
}