Work with video

This commit is contained in:
Mike Phares 2024-01-27 18:11:24 -07:00
parent cfe43360fc
commit 4081a73b9d
20 changed files with 210 additions and 165 deletions

View File

@ -431,7 +431,8 @@ public partial class E_Distance : IDistance
if (faceDistanceContainer.Face.Mapping.MappingFromLocation.AreaPermyriad < distanceLimits.FaceAreaPermyriad) if (faceDistanceContainer.Face.Mapping.MappingFromLocation.AreaPermyriad < distanceLimits.FaceAreaPermyriad)
continue; continue;
if (faceDistanceContainer.Face.Mapping.MappingFromFilterPre.InSkipCollection is not null && faceDistanceContainer.Face.Mapping.MappingFromFilterPre.InSkipCollection.Value) if (faceDistanceContainer.Face.Mapping.MappingFromFilterPre.InSkipCollection is not null && faceDistanceContainer.Face.Mapping.MappingFromFilterPre.InSkipCollection.Value)
throw new NotSupportedException(nameof(PreFilterSetFaceDistances)); // throw new NotSupportedException(nameof(PreFilterSetFaceDistances));
continue;
if (faceDistanceContainer.Face.Mapping.MappingFromFilterPre.IsFocusModel is not null && !faceDistanceContainer.Face.Mapping.MappingFromFilterPre.IsFocusModel.Value) if (faceDistanceContainer.Face.Mapping.MappingFromFilterPre.IsFocusModel is not null && !faceDistanceContainer.Face.Mapping.MappingFromFilterPre.IsFocusModel.Value)
continue; continue;
if (faceDistanceContainer.Face.Mapping.MappingFromFilterPre.IsFocusRelativePath is not null && !faceDistanceContainer.Face.Mapping.MappingFromFilterPre.IsFocusRelativePath.Value) if (faceDistanceContainer.Face.Mapping.MappingFromFilterPre.IsFocusRelativePath is not null && !faceDistanceContainer.Face.Mapping.MappingFromFilterPre.IsFocusRelativePath.Value)

View File

@ -29,9 +29,9 @@ public class DuplicateSearch
else else
{ {
Configuration.Verify(configuration, requireExist: false); Configuration.Verify(configuration, requireExist: false);
Container[] containers = GetContainers(ticks, configuration);
string argZero = args.Count > 0 ? Path.GetFullPath(args[0]) : Path.GetFullPath(configuration.RootDirectory); string argZero = args.Count > 0 ? Path.GetFullPath(args[0]) : Path.GetFullPath(configuration.RootDirectory);
bool argZeroIsConfigurationRootDirectory = configuration.RootDirectory == argZero; bool argZeroIsConfigurationRootDirectory = configuration.RootDirectory == argZero;
Container[] containers = GetContainers(appSettings, ticks, argZero, configuration, argZeroIsConfigurationRootDirectory);
string destinationRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(configuration, "Z) Moved"); string destinationRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(configuration, "Z) Moved");
List<int> preloadIds = GetPreloadIds(destinationRoot); List<int> preloadIds = GetPreloadIds(destinationRoot);
Dictionary<int, List<MappingFromItem?>> idToCollection = GetIdToCollection(argZero, configuration, argZeroIsConfigurationRootDirectory, containers, destinationRoot, preloadIds); Dictionary<int, List<MappingFromItem?>> idToCollection = GetIdToCollection(argZero, configuration, argZeroIsConfigurationRootDirectory, containers, destinationRoot, preloadIds);
@ -124,7 +124,7 @@ public class DuplicateSearch
} }
} }
private static Container[] GetContainers(AppSettings appSettings, long ticks, string argZero, Configuration configuration, bool argZeroIsConfigurationRootDirectory) private static Container[] GetContainers(long ticks, Configuration configuration)
{ {
int f; int f;
Container[] containers; Container[] containers;

View File

@ -278,7 +278,6 @@ public partial class DlibDotNet
ReadOnlyDictionary<long, List<int>> personKeyToIds; ReadOnlyDictionary<long, List<int>> personKeyToIds;
ReadOnlyCollection<string[]>? filesCollection = null; ReadOnlyCollection<string[]>? filesCollection = null;
bool runToDoCollectionFirst = GetRunToDoCollectionFirst(ticks); bool runToDoCollectionFirst = GetRunToDoCollectionFirst(ticks);
Dictionary<int, List<MappingFromPhotoPrism>> fileNameToCollection;
(aResultsFullGroupDirectory, bResultsFullGroupDirectory) = GetResultsFullGroupDirectories(); (aResultsFullGroupDirectory, bResultsFullGroupDirectory) = GetResultsFullGroupDirectories();
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
Shared.Models.Stateless.Methods.IPath.ChangeDateForEmptyDirectories(_Configuration.PropertyConfiguration.RootDirectory, ticks); Shared.Models.Stateless.Methods.IPath.ChangeDateForEmptyDirectories(_Configuration.PropertyConfiguration.RootDirectory, ticks);
@ -350,11 +349,11 @@ public partial class DlibDotNet
(t, containers) = Shared.Models.Stateless.Methods.IContainer.GetContainers(_Configuration.PropertyConfiguration, aPropertySingletonDirectory, filesCollectionRootDirectory, filesCollection); (t, containers) = Shared.Models.Stateless.Methods.IContainer.GetContainers(_Configuration.PropertyConfiguration, aPropertySingletonDirectory, filesCollectionRootDirectory, filesCollection);
progressBar.Tick(); progressBar.Tick();
} }
fileNameToCollection = !Directory.Exists(fPhotoPrismSingletonDirectory) ? fileNameToCollection = [] : F_PhotoPrism.GetFileNameToCollection(fPhotoPrismSingletonDirectory); ReadOnlyCollection<Container> readOnlyContainers = new(containers);
B_Metadata metadata = new(_Configuration.PropertyConfiguration, _Configuration.ForceMetadataLastWriteTimeToCreationTime, _Configuration.PropertiesChangedForMetadata, bResultsFullGroupDirectory); SaveDistinctIds(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, readOnlyContainers);
mapLogic ??= new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, _Distance, personContainers, ticks, a2PeopleContentDirectory, a2PeopleSingletonDirectory, eDistanceContentDirectory); mapLogic ??= new(_AppSettings.MaxDegreeOfParallelism, _Configuration.PropertyConfiguration, _MapConfiguration, _Distance, personContainers, ticks, a2PeopleContentDirectory, a2PeopleSingletonDirectory, eDistanceContentDirectory);
FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, t, containers, propertyLogic, metadata, fileNameToCollection, mapLogic); FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, fPhotoPrismSingletonDirectory, t, readOnlyContainers, propertyLogic, mapLogic);
ReadOnlyCollection<Item> distinctFilteredItems = Shared.Models.Stateless.Methods.IContainer.GetItems(_Configuration.PropertyConfiguration, new(containers), distinctItems: true, filterItems: true); ReadOnlyCollection<Item> distinctFilteredItems = Shared.Models.Stateless.Methods.IContainer.GetItems(_Configuration.PropertyConfiguration, readOnlyContainers, distinctItems: true, filterItems: true);
if (_Configuration.LookForAbandoned) if (_Configuration.LookForAbandoned)
{ {
string dResultsFullGroupDirectory; string dResultsFullGroupDirectory;
@ -362,12 +361,12 @@ public partial class DlibDotNet
foreach (string outputResolution in _Configuration.OutputResolutions) foreach (string outputResolution in _Configuration.OutputResolutions)
{ {
(cResultsFullGroupDirectory, _, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory) = GetResultsFullGroupDirectories(outputResolution); (cResultsFullGroupDirectory, _, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory) = GetResultsFullGroupDirectories(outputResolution);
mapLogic.LookForAbandoned(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, containers, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory); mapLogic.LookForAbandoned(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, readOnlyContainers, cResultsFullGroupDirectory, dResultsFullGroupDirectory, d2ResultsFullGroupDirectory);
} }
} }
_Distance.Clear(); _Distance.Clear();
ReadOnlyCollection<Shared.Models.Face> distinctFilteredFaces = Map.Models.Stateless.Methods.IMapLogic.GetFaces(distinctFilteredItems); ReadOnlyCollection<Shared.Models.Face> distinctFilteredFaces = Map.Models.Stateless.Methods.IMapLogic.GetFaces(distinctFilteredItems);
ReadOnlyCollection<Mapping> distinctFilteredMappingCollection = GetMappings(_Configuration.PropertyConfiguration, eDistanceContentDirectory, containers, mapLogic, distinctItems: true); ReadOnlyCollection<Mapping> distinctFilteredMappingCollection = GetMappings(_Configuration.PropertyConfiguration, eDistanceContentDirectory, readOnlyContainers, mapLogic, distinctItems: true);
if (runToDoCollectionFirst) if (runToDoCollectionFirst)
{ {
if (!Directory.Exists(eDistanceContentDirectory)) if (!Directory.Exists(eDistanceContentDirectory))
@ -391,7 +390,7 @@ public partial class DlibDotNet
&& outputResolution == _Configuration.OutputResolutions[0] && outputResolution == _Configuration.OutputResolutions[0]
&& _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution) && _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution)
&& _Exceptions.Count == 0) && _Exceptions.Count == 0)
MapLogic(ticks, new(containers), fPhotoPrismContentDirectory, mapLogic, outputResolution, new(personKeyToIds), distinctFilteredFaces, distinctFilteredMappingCollection); MapLogic(ticks, readOnlyContainers, fPhotoPrismContentDirectory, mapLogic, outputResolution, new(personKeyToIds), distinctFilteredFaces, distinctFilteredMappingCollection);
if (runToDoCollectionFirst && _Configuration.SaveRandomForOutputResolutions.Contains(outputResolution) && personKeyToIds.Count > 0 && distinctFilteredMappingCollection.Count > 0) if (runToDoCollectionFirst && _Configuration.SaveRandomForOutputResolutions.Contains(outputResolution) && personKeyToIds.Count > 0 && distinctFilteredMappingCollection.Count > 0)
_Random.Random(_Configuration.PropertyConfiguration, _Configuration.RadomUseBirthdayMinimum, _Configuration.ValidKeyWordsToIgnoreInRandom, outputResolution, personKeyToIds, notNineCollection, distinctFilteredMappingCollection); _Random.Random(_Configuration.PropertyConfiguration, _Configuration.RadomUseBirthdayMinimum, _Configuration.ValidKeyWordsToIgnoreInRandom, outputResolution, personKeyToIds, notNineCollection, distinctFilteredMappingCollection);
if (_IsEnvironment.Development) if (_IsEnvironment.Development)
@ -509,7 +508,7 @@ public partial class DlibDotNet
return result; return result;
} }
private void FullDoWork(string argZero, string propertyRoot, long ticks, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, int t, Container[] containers, A_Property propertyLogic, B_Metadata metadata, Dictionary<int, List<MappingFromPhotoPrism>> fileNameToCollection, MapLogic mapLogic) private void FullDoWork(string argZero, string propertyRoot, long ticks, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, string fPhotoPrismSingletonDirectory, int t, ReadOnlyCollection<Container> readOnlyContainers, A_Property propertyLogic, MapLogic mapLogic)
{ {
int total; int total;
int notMapped; int notMapped;
@ -525,10 +524,12 @@ public partial class DlibDotNet
string dResultsFullGroupDirectory; string dResultsFullGroupDirectory;
string c2ResultsFullGroupDirectory; string c2ResultsFullGroupDirectory;
string d2ResultsFullGroupDirectory; string d2ResultsFullGroupDirectory;
int containersLength = containers.Length; int containersLength = readOnlyContainers.Count;
List<Tuple<string, DateTime>> sourceDirectoryChanges = []; List<Tuple<string, DateTime>> sourceDirectoryChanges = [];
int maxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism; int maxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism;
Dictionary<int, List<MappingFromPhotoPrism>> fileNameToCollection = !Directory.Exists(fPhotoPrismSingletonDirectory) ? fileNameToCollection = [] : F_PhotoPrism.GetFileNameToCollection(fPhotoPrismSingletonDirectory);
string dResultsDateGroupDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(D_Face)); string dResultsDateGroupDirectory = Property.Models.Stateless.IResult.GetResultsDateGroupDirectory(_Configuration.PropertyConfiguration, nameof(D_Face));
B_Metadata metadata = new(_Configuration.PropertyConfiguration, _Configuration.ForceMetadataLastWriteTimeToCreationTime, _Configuration.PropertiesChangedForMetadata, bResultsFullGroupDirectory);
foreach (string outputResolution in _Configuration.OutputResolutions) foreach (string outputResolution in _Configuration.OutputResolutions)
{ {
total = 0; total = 0;
@ -538,9 +539,9 @@ public partial class DlibDotNet
_Resize.Update(cResultsFullGroupDirectory); _Resize.Update(cResultsFullGroupDirectory);
_FaceParts.Update(d2ResultsFullGroupDirectory); _FaceParts.Update(d2ResultsFullGroupDirectory);
_BlurHasher.Update(c2ResultsFullGroupDirectory); _BlurHasher.Update(c2ResultsFullGroupDirectory);
for (int i = 0; i < containers.Length; i++) for (int i = 0; i < readOnlyContainers.Count; i++)
{ {
container = containers[i]; container = readOnlyContainers[i];
if (container.Items.Count == 0) if (container.Items.Count == 0)
continue; continue;
if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero)) if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero))
@ -595,21 +596,45 @@ public partial class DlibDotNet
} }
} }
private ReadOnlyCollection<Mapping> GetMappings(Property.Models.Configuration propertyConfiguration, string eDistanceContentDirectory, Container[] containers, MapLogic mapLogic, bool distinctItems) private static void SaveDistinctIds(Property.Models.Configuration propertyConfiguration, string bResultsFullGroupDirectory, ReadOnlyCollection<Container> readOnlyContainers)
{
List<int> distinct = [];
string bMetadataCollectionDirectory = Path.Combine(bResultsFullGroupDirectory, propertyConfiguration.ResultCollection);
if (!Directory.Exists(bMetadataCollectionDirectory))
_ = Directory.CreateDirectory(bMetadataCollectionDirectory);
foreach (Container container in readOnlyContainers)
{
if (container.Items.Count == 0)
continue;
foreach (Item item in container.Items)
{
if (item.Property?.Id is null)
continue;
if (distinct.Contains(item.Property.Id.Value))
continue;
distinct.Add(item.Property.Id.Value);
}
}
distinct.Sort();
string json = JsonSerializer.Serialize(distinct);
_ = Shared.Models.Stateless.Methods.IPath.WriteAllText(Path.Combine(bMetadataCollectionDirectory, ".json"), json, updateDateWhenMatches: false, compareBeforeWrite: true, updateToWhenMatches: null);
}
private ReadOnlyCollection<Mapping> GetMappings(Property.Models.Configuration propertyConfiguration, string eDistanceContentDirectory, ReadOnlyCollection<Container> readOnlyContainers, MapLogic mapLogic, bool distinctItems)
{ {
ReadOnlyCollection<Mapping> results; ReadOnlyCollection<Mapping> results;
int count = 0; int count = 0;
int notMapped; int notMapped;
Mapping mapping; Mapping mapping;
bool anyValidFaces; bool anyValidFaces;
List<int> distinct = [];
string focusRelativePath; string focusRelativePath;
bool? isFocusRelativePath; bool? isFocusRelativePath;
List<int> distinct = [];
DateTime[] containerDateTimes; DateTime[] containerDateTimes;
IEnumerable<Item> filteredItems; IEnumerable<Item> filteredItems;
MappingFromItem mappingFromItem; MappingFromItem mappingFromItem;
List<Mapping> mappingCollection = []; List<Mapping> mappingCollection = [];
foreach (Container container in containers) foreach (Container container in readOnlyContainers)
{ {
if (container.Items.Count == 0) if (container.Items.Count == 0)
continue; continue;
@ -858,6 +883,7 @@ public partial class DlibDotNet
configuration.DistanceRenameToMatch, configuration.DistanceRenameToMatch,
configuration.FaceConfidencePercent, configuration.FaceConfidencePercent,
configuration.FaceDistancePermyriad, configuration.FaceDistancePermyriad,
configuration.LinkedAlpha,
configuration.LocationContainerDebugDirectory, configuration.LocationContainerDebugDirectory,
configuration.LocationContainerDirectoryPattern, configuration.LocationContainerDirectoryPattern,
configuration.LocationContainerDistanceGroupMinimum, configuration.LocationContainerDistanceGroupMinimum,
@ -885,41 +911,21 @@ public partial class DlibDotNet
private (Mapping, int) GetMappingAndUpdateMappingFromPerson(MapLogic mapLogic, Item item, bool? isFocusRelativePath, MappingFromItem mappingFromItem) private (Mapping, int) GetMappingAndUpdateMappingFromPerson(MapLogic mapLogic, Item item, bool? isFocusRelativePath, MappingFromItem mappingFromItem)
{ {
Mapping result; Mapping result;
bool? canReMap;
int? eyeα = null; int? eyeα = null;
bool? isFocusPerson;
bool? eyeReview = null; bool? eyeReview = null;
bool? inSkipCollection;
int confidencePercent = 0; int confidencePercent = 0;
int faceAreaPermyriad = 0; int faceAreaPermyriad = 0;
int wholePercentRectangle;
string deterministicHashCodeKey;
MappingFromLocation? mappingFromLocation;
MappingFromFilterPre mappingFromFilterPre;
MappingFromFilterPost mappingFromFilterPost;
bool? isFocusModel = GetIsFocusModel(item.Property); bool? isFocusModel = GetIsFocusModel(item.Property);
long[] jLinkResolvedPersonKeys = _JLinkResolvedDirectories.Select(l => l.PersonKey).ToArray(); long[] jLinkResolvedPersonKeys = _JLinkResolvedDirectories.Select(l => l.PersonKey).ToArray();
ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>? wholePercentagesToPersonContainers = mapLogic.GetWholePercentagesToPersonContainers(item.Property?.Id); ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>? wholePercentagesToPersonContainers = mapLogic.GetWholePercentagesToPersonContainers(mappingFromItem.Id);
if (item.Property?.Id is null) int wholePercentRectangle = Shared.Models.Stateless.Methods.ILocation.GetWholePercentages(Shared.Models.Stateless.ILocation.Digits);
{ string deterministicHashCodeKey = IMapping.GetDeterministicHashCodeKey(item.FilePath, Shared.Models.Stateless.ILocation.Digits);
canReMap = null; MappingFromLocation? mappingFromLocation = new(faceAreaPermyriad, confidencePercent, deterministicHashCodeKey, eyeα, eyeReview, wholePercentRectangle);
isFocusPerson = null; bool? inSkipCollection = mapLogic.InSkipCollection(mappingFromItem.Id, mappingFromLocation);
inSkipCollection = null; MappingFromFilterPre mappingFromFilterPre = new(inSkipCollection, isFocusModel, isFocusRelativePath);
mappingFromLocation = null; bool? canReMap = Map.Models.Stateless.Methods.IMapLogic.CanReMap(jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation);
mappingFromFilterPost = new(canReMap, inSkipCollection, isFocusPerson); bool? isFocusPerson = mapLogic.IsFocusPerson(_Configuration.SkipPersonWithMoreThen, jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation);
mappingFromFilterPre = new(inSkipCollection, isFocusModel, isFocusRelativePath); MappingFromFilterPost mappingFromFilterPost = new(canReMap, inSkipCollection, isFocusPerson);
}
else
{
wholePercentRectangle = Shared.Models.Stateless.Methods.ILocation.GetWholePercentages(Shared.Models.Stateless.ILocation.Digits);
deterministicHashCodeKey = IMapping.GetDeterministicHashCodeKey(item.FilePath, Shared.Models.Stateless.ILocation.Digits);
mappingFromLocation = new(faceAreaPermyriad, confidencePercent, deterministicHashCodeKey, eyeα, eyeReview, wholePercentRectangle);
inSkipCollection = mapLogic.InSkipCollection(item.Property.Id.Value, mappingFromLocation);
mappingFromFilterPre = new(inSkipCollection, isFocusModel, isFocusRelativePath);
canReMap = Map.Models.Stateless.Methods.IMapLogic.CanReMap(jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation);
isFocusPerson = mapLogic.IsFocusPerson(_Configuration.SkipPersonWithMoreThen, jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation);
mappingFromFilterPost = new(canReMap, inSkipCollection, isFocusPerson);
}
result = new(item.FilePath, mappingFromFilterPost, mappingFromFilterPre, mappingFromItem, mappingFromLocation, mappingFromPhotoPrismCollection: null); result = new(item.FilePath, mappingFromFilterPost, mappingFromFilterPre, mappingFromItem, mappingFromLocation, mappingFromPhotoPrismCollection: null);
int notMapped = mapLogic.UpdateMappingFromPerson(wholePercentagesToPersonContainers, result); int notMapped = mapLogic.UpdateMappingFromPerson(wholePercentagesToPersonContainers, result);
return (result, notMapped); return (result, notMapped);

View File

@ -29,6 +29,7 @@ public class Configuration
public string? GenealogicalDataCommunicationFile { get; set; } public string? GenealogicalDataCommunicationFile { get; set; }
public string[]? IgnoreExtensions { get; set; } public string[]? IgnoreExtensions { get; set; }
public string[]? JLinks { get; set; } public string[]? JLinks { get; set; }
public string? LinkedAlpha { get; set; }
public string[]? LoadOrCreateThenSaveDistanceResultsForOutputResolutions { get; set; } public string[]? LoadOrCreateThenSaveDistanceResultsForOutputResolutions { get; set; }
public string[]? LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { get; set; } public string[]? LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { get; set; }
public bool? LoadPhotoPrismLocations { get; set; } public bool? LoadPhotoPrismLocations { get; set; }
@ -131,6 +132,7 @@ public class Configuration
if (configuration?.GenealogicalDataCommunicationFile is null) throw new NullReferenceException(nameof(configuration.GenealogicalDataCommunicationFile)); if (configuration?.GenealogicalDataCommunicationFile is null) throw new NullReferenceException(nameof(configuration.GenealogicalDataCommunicationFile));
// if (configuration?.IgnoreExtensions is null) throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); // if (configuration?.IgnoreExtensions is null) throw new NullReferenceException(nameof(configuration.IgnoreExtensions));
// if (configuration?.JLinks is null) throw new NullReferenceException(nameof(configuration.JLinks)); // if (configuration?.JLinks is null) throw new NullReferenceException(nameof(configuration.JLinks));
// if (configuration?.LinkedAlpha is null) throw new NullReferenceException(nameof(configuration.LinkedAlpha));
// if (configuration?.LoadOrCreateThenSaveDistanceResultsForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions)); // if (configuration?.LoadOrCreateThenSaveDistanceResultsForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions));
// if (configuration?.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions)); // if (configuration?.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions));
if (configuration?.LoadPhotoPrismLocations is null) throw new NullReferenceException(nameof(configuration.LoadPhotoPrismLocations)); if (configuration?.LoadPhotoPrismLocations is null) throw new NullReferenceException(nameof(configuration.LoadPhotoPrismLocations));
@ -220,6 +222,7 @@ public class Configuration
configuration.GenealogicalDataCommunicationFile, configuration.GenealogicalDataCommunicationFile,
configuration.IgnoreExtensions ?? [], configuration.IgnoreExtensions ?? [],
configuration.JLinks ?? [], configuration.JLinks ?? [],
configuration.LinkedAlpha,
configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions ?? [], configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions ?? [],
configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions ?? [], configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions ?? [],
configuration.LoadPhotoPrismLocations.Value, configuration.LoadPhotoPrismLocations.Value,

View File

@ -23,6 +23,7 @@ public record Configuration(Property.Models.Configuration PropertyConfiguration,
string GenealogicalDataCommunicationFile, string GenealogicalDataCommunicationFile,
string[] IgnoreExtensions, string[] IgnoreExtensions,
string[] JLinks, string[] JLinks,
string? LinkedAlpha,
string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions, string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions,
string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions, string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions,
bool LoadPhotoPrismLocations, bool LoadPhotoPrismLocations,

View File

@ -5,6 +5,7 @@ public record Configuration(bool DeletePossibleDuplicates,
bool DistanceRenameToMatch, bool DistanceRenameToMatch,
int FaceConfidencePercent, int FaceConfidencePercent,
int FaceDistancePermyriad, int FaceDistancePermyriad,
string? LinkedAlpha,
string LocationContainerDebugDirectory, string LocationContainerDebugDirectory,
string LocationContainerDirectoryPattern, string LocationContainerDirectoryPattern,
int LocationContainerDistanceGroupMinimum, int LocationContainerDistanceGroupMinimum,

View File

@ -225,11 +225,12 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
_Ticks = ticks; _Ticks = ticks;
_Configuration = configuration; _Configuration = configuration;
_PropertyConfiguration = propertyConfiguration; _PropertyConfiguration = propertyConfiguration;
ReadOnlyDictionary<long, int> readOnlyPersonKeyToCount; List<LocationContainer> locationContainers = [];
List<PersonContainer> notMappedPersonContainers = []; List<PersonContainer> notMappedPersonContainers = [];
ReadOnlyDictionary<long, int> readOnlyPersonKeyToCount;
Dictionary<int, List<(string, int)>> skipCollection = []; Dictionary<int, List<(string, int)>> skipCollection = [];
Dictionary<int, List<(string, int)>> skipNotSkipCollection = []; Dictionary<int, List<(string, int)>> skipNotSkipCollection = [];
List<LocationContainer> locationContainers = []; ReadOnlyDictionary<int, List<(string, int)>> readOnlyskipCollection;
string? rootDirectoryParent = Path.GetDirectoryName(propertyConfiguration.RootDirectory); string? rootDirectoryParent = Path.GetDirectoryName(propertyConfiguration.RootDirectory);
string eDistanceContentTicksDirectory = Path.Combine(eDistanceContentDirectory, ticks.ToString()); string eDistanceContentTicksDirectory = Path.Combine(eDistanceContentDirectory, ticks.ToString());
ReadOnlyDictionary<int, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>> idThenWholePercentagesToPersonContainers; ReadOnlyDictionary<int, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>> idThenWholePercentagesToPersonContainers;
@ -293,8 +294,10 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
readOnlyPersonKeyToCount, readOnlyPersonKeyToCount,
readOnlyPossiblyNewPersonDisplayDirectoryNamesAndPersonContainer); readOnlyPossiblyNewPersonDisplayDirectoryNamesAndPersonContainer);
idThenWholePercentagesToPersonContainers = Stateless.MapLogic.GetIdThenWholePercentagesToPersonContainers(configuration, idThenWholePercentagesToPersonContainers = Stateless.MapLogic.GetIdThenWholePercentagesToPersonContainers(configuration,
skipCollection,
readOnlyPersonKeyFormattedToPersonContainer, readOnlyPersonKeyFormattedToPersonContainer,
personKeyFormattedIdThenWholePercentagesCollection); personKeyFormattedIdThenWholePercentagesCollection);
readOnlyskipCollection = new(skipCollection);
notMappedPersonContainers.AddRange(Stateless.MapLogic.GetNotMappedPersonContainers(configuration, notMappedPersonContainers.AddRange(Stateless.MapLogic.GetNotMappedPersonContainers(configuration,
ticks, ticks,
personContainers, personContainers,
@ -304,7 +307,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
configuration, configuration,
ticks, ticks,
personContainers, personContainers,
skipCollection, readOnlyskipCollection,
records)); records));
int lossCount = records.Count - locationContainers.Count; int lossCount = records.Count - locationContainers.Count;
int unableToMatchCount = records.Count - personKeyFormattedIdThenWholePercentagesCollection.Count; int unableToMatchCount = records.Count - personKeyFormattedIdThenWholePercentagesCollection.Count;
@ -1335,11 +1338,11 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic
return result; return result;
} }
public void LookForAbandoned(Property.Models.Configuration propertyConfiguration, string bResultsFullGroupDirectory, Container[] containers, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory) public void LookForAbandoned(Property.Models.Configuration propertyConfiguration, string bResultsFullGroupDirectory, ReadOnlyCollection<Container> readOnlyContainers, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory)
{ {
string[] directories; string[] directories;
string? directoryName; string? directoryName;
List<int> distinctFilteredIds = IContainer.GetFilteredDistinctIds(propertyConfiguration, containers); List<int> distinctFilteredIds = IContainer.GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers);
LookForAbandoned(propertyConfiguration, distinctFilteredIds); LookForAbandoned(propertyConfiguration, distinctFilteredIds);
Stateless.LookForAbandonedLogic.LookForAbandoned(propertyConfiguration, bResultsFullGroupDirectory, distinctFilteredIds); Stateless.LookForAbandonedLogic.LookForAbandoned(propertyConfiguration, bResultsFullGroupDirectory, distinctFilteredIds);
directories = Directory.GetDirectories(cResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly); directories = Directory.GetDirectories(cResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly);

View File

@ -9,19 +9,21 @@ using View_by_Distance.Shared.Models.Stateless.Methods;
namespace View_by_Distance.Map.Models.Stateless; namespace View_by_Distance.Map.Models.Stateless;
internal record Record(string PersonKeyFormatted, internal record Record(int DirectoryNumber,
int DirectoryNumber,
string? PersonDisplayDirectoryName,
bool? IsDefault, bool? IsDefault,
FilePath MappedFaceFilePath); int? LinksCount,
FilePath MappedFaceFilePath,
string? PersonDisplayDirectoryName,
string PersonKeyFormatted);
internal abstract class DistanceLogic internal abstract class DistanceLogic
{ {
internal record TicksDirectory(string Directory, internal record TicksDirectory(DateTime AlternateDirectoryDateTime,
string DirectoryName, string Directory,
DateTime DirectoryDateTime, DateTime DirectoryDateTime,
DateTime AlternateDirectoryDateTime, string DirectoryName,
bool? IsLocationContainerDebugDirectory,
float? TotalDays); float? TotalDays);
private static void MoveTo(string actionDirectory, TicksDirectory ticksDirectory, string directory, string personKeyFormatted, string yearDirectoryName, string alphaDirectoryName, string[] files, string[] facesFileNames) private static void MoveTo(string actionDirectory, TicksDirectory ticksDirectory, string directory, string personKeyFormatted, string yearDirectoryName, string alphaDirectoryName, string[] files, string[] facesFileNames)
@ -89,6 +91,8 @@ internal abstract class DistanceLogic
DirectoryInfo directoryInfo; DirectoryInfo directoryInfo;
long? lastDirectoryTicks = null; long? lastDirectoryTicks = null;
DateTime dateTime = DateTime.Now; DateTime dateTime = DateTime.Now;
DateTime alternateDirectoryDateTime;
bool? isLocationContainerDebugDirectory;
long month = dateTime.AddMonths(1).Ticks - dateTime.Ticks; long month = dateTime.AddMonths(1).Ticks - dateTime.Ticks;
for (int i = 1; i < 5; i++) for (int i = 1; i < 5; i++)
_ = IPath.DeleteEmptyDirectories(eDistanceContentDirectory); _ = IPath.DeleteEmptyDirectories(eDistanceContentDirectory);
@ -125,8 +129,10 @@ internal abstract class DistanceLogic
Directory.SetCreationTime(ticksDirectory, new DateTime(directoryTicks)); Directory.SetCreationTime(ticksDirectory, new DateTime(directoryTicks));
if (directoryInfo.LastWriteTime.Ticks != directoryTicks) if (directoryInfo.LastWriteTime.Ticks != directoryTicks)
Directory.SetLastWriteTime(ticksDirectory, new DateTime(directoryTicks)); Directory.SetLastWriteTime(ticksDirectory, new DateTime(directoryTicks));
alternateDirectoryDateTime = new DateTime(directoryDateTime.Year, directoryDateTime.Month, directoryDateTime.Day).AddMonths(1);
isLocationContainerDebugDirectory = configuration.LocationContainerDebugDirectory is null ? null : ticksDirectoryName.EndsWith(configuration.LocationContainerDebugDirectory);
totalDays = lastDirectoryTicks is null || new TimeSpan(dateTime.Ticks - directoryTicks).TotalDays < 1 ? null : (float)new TimeSpan(directoryTicks - lastDirectoryTicks.Value).TotalDays; totalDays = lastDirectoryTicks is null || new TimeSpan(dateTime.Ticks - directoryTicks).TotalDays < 1 ? null : (float)new TimeSpan(directoryTicks - lastDirectoryTicks.Value).TotalDays;
results.Add(new(ticksDirectory, ticksDirectoryName, new(directoryTicks), new DateTime(directoryDateTime.Year, directoryDateTime.Month, directoryDateTime.Day).AddMonths(1), totalDays)); results.Add(new(alternateDirectoryDateTime, ticksDirectory, new(directoryTicks), ticksDirectoryName, isLocationContainerDebugDirectory, totalDays));
if (directoryDateTime.Hour == 0 && directoryDateTime.Minute == 0 && directoryDateTime.Second == 0) if (directoryDateTime.Hour == 0 && directoryDateTime.Minute == 0 && directoryDateTime.Second == 0)
continue; continue;
lastDirectoryTicks = directoryTicks; lastDirectoryTicks = directoryTicks;
@ -210,7 +216,7 @@ internal abstract class DistanceLogic
} }
} }
private static List<Record> GetRecords(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, bool? isDefault, string[] files, int directoryNumber, string personKeyFormatted, List<string> distinct, string? personDisplayDirectoryName) private static List<Record> GetRecords(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, bool? isDefault, string[] files, int directoryNumber, string personKeyFormatted, int? linksCount, List<string> distinct, string? personDisplayDirectoryName)
{ {
List<Record> results = []; List<Record> results = [];
string fileName; string fileName;
@ -239,7 +245,7 @@ internal abstract class DistanceLogic
continue; continue;
} }
distinct.Add(fileName); distinct.Add(fileName);
results.Add(new(personKeyFormatted, directoryNumber, personDisplayDirectoryName, isDefault, filePath)); results.Add(new(directoryNumber, isDefault, linksCount, filePath, personDisplayDirectoryName, personKeyFormatted));
} }
return results; return results;
} }
@ -263,6 +269,23 @@ internal abstract class DistanceLogic
Directory.Move(personKeyDirectory, newestPersonKeyDirectory); Directory.Move(personKeyDirectory, newestPersonKeyDirectory);
} }
private static int? GetLinksCount(string yearDirectory)
{
int? result;
string[] yearDirectoryNameSegments = Path.GetFileName(yearDirectory).Split('-');
if (yearDirectoryNameSegments.Length != 3)
result = null;
else
{
string lastSegment = yearDirectoryNameSegments[^1];
if (lastSegment.Length != 3 || !lastSegment.All(l => l == lastSegment[0]))
result = null;
else
result = lastSegment[0] - 65;
}
return result;
}
internal static List<Record> DeleteEmptyDirectoriesAndGetCollection(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, long ticks, string eDistanceContentDirectory, ReadOnlyDictionary<string, string> personKeyFormattedToNewestPersonKeyFormatted, ReadOnlyCollection<string> personKeyFormattedCollection) internal static List<Record> DeleteEmptyDirectoriesAndGetCollection(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, long ticks, string eDistanceContentDirectory, ReadOnlyDictionary<string, string> personKeyFormattedToNewestPersonKeyFormatted, ReadOnlyCollection<string> personKeyFormattedCollection)
{ {
List<Record> results = []; List<Record> results = [];
@ -270,6 +293,7 @@ internal abstract class DistanceLogic
string message; string message;
string[] files; string[] files;
bool? isDefault; bool? isDefault;
int? linksCount;
int totalSeconds; int totalSeconds;
DateTime dateTime; DateTime dateTime;
TimeSpan timeSpan; TimeSpan timeSpan;
@ -327,6 +351,10 @@ internal abstract class DistanceLogic
{ {
if (check && !Directory.Exists(yearDirectory)) if (check && !Directory.Exists(yearDirectory))
continue; continue;
if (ticksDirectory.IsLocationContainerDebugDirectory is null || !ticksDirectory.IsLocationContainerDebugDirectory.Value)
linksCount = null;
else
linksCount = GetLinksCount(yearDirectory);
if (ticksDirectory.DirectoryName != configuration.LocationContainerDebugDirectory) if (ticksDirectory.DirectoryName != configuration.LocationContainerDebugDirectory)
{ {
files = Directory.GetFiles(yearDirectory, "*", SearchOption.TopDirectoryOnly); files = Directory.GetFiles(yearDirectory, "*", SearchOption.TopDirectoryOnly);
@ -338,7 +366,7 @@ internal abstract class DistanceLogic
isDefault = null; isDefault = null;
personDisplayDirectoryName = null; personDisplayDirectoryName = null;
files = Directory.GetFiles(yearDirectory, "*", SearchOption.TopDirectoryOnly); files = Directory.GetFiles(yearDirectory, "*", SearchOption.TopDirectoryOnly);
results.AddRange(GetRecords(propertyConfiguration, configuration, isDefault, files, directoryNumber, personKeyFormatted, distinct, personDisplayDirectoryName)); results.AddRange(GetRecords(propertyConfiguration, configuration, isDefault, files, directoryNumber, personKeyFormatted, linksCount, distinct, personDisplayDirectoryName));
files = Directory.GetFiles(yearDirectory, "*.lnk", SearchOption.AllDirectories); files = Directory.GetFiles(yearDirectory, "*.lnk", SearchOption.AllDirectories);
foreach (string file in files) foreach (string file in files)
File.Delete(file); File.Delete(file);
@ -426,7 +454,7 @@ internal abstract class DistanceLogic
Directory.Move(personNameDirectory, personFirstInitialDirectory); Directory.Move(personNameDirectory, personFirstInitialDirectory);
files = Directory.GetFiles(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly); files = Directory.GetFiles(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly);
} }
results.AddRange(GetRecords(propertyConfiguration, configuration, isDefault, files, directoryNumber, personKeyFormatted, distinct, personDisplayDirectoryName)); results.AddRange(GetRecords(propertyConfiguration, configuration, isDefault, files, directoryNumber, personKeyFormatted, linksCount, distinct, personDisplayDirectoryName));
personNameLinkDirectories = Directory.GetDirectories(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly); personNameLinkDirectories = Directory.GetDirectories(personFirstInitialDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string personNameLinkDirectory in personNameLinkDirectories) foreach (string personNameLinkDirectory in personNameLinkDirectories)
{ {

View File

@ -27,6 +27,7 @@ internal abstract class MapLogic
internal record PersonKeyFormattedIdThenWholePercentages(string PersonKeyFormatted, internal record PersonKeyFormattedIdThenWholePercentages(string PersonKeyFormatted,
string? PersonDisplayDirectoryName, string? PersonDisplayDirectoryName,
bool? IsDefault, bool? IsDefault,
int? LinksCount,
FilePath MappedFaceFilePath, FilePath MappedFaceFilePath,
int Id, int Id,
int WholePercentages); int WholePercentages);
@ -298,13 +299,14 @@ internal abstract class MapLogic
return results; return results;
} }
private static Dictionary<int, Dictionary<int, List<PersonContainer>>> GetAll(Configuration configuration, ReadOnlyDictionary<string, PersonContainer> personKeyFormattedToPersonContainer, ReadOnlyCollection<PersonKeyFormattedIdThenWholePercentages> personKeyFormattedIdThenWholePercentagesCollection) private static Dictionary<int, Dictionary<int, List<PersonContainer>>> GetAll(Configuration configuration, Dictionary<int, List<(string, int)>> skipCollection, ReadOnlyDictionary<string, PersonContainer> personKeyFormattedToPersonContainer, ReadOnlyCollection<PersonKeyFormattedIdThenWholePercentages> personKeyFormattedIdThenWholePercentagesCollection)
{ {
Dictionary<int, Dictionary<int, List<PersonContainer>>> results = []; Dictionary<int, Dictionary<int, List<PersonContainer>>> results = [];
PersonBirthday? personBirthday; PersonBirthday? personBirthday;
PersonContainer? personContainer; PersonContainer? personContainer;
List<PersonContainer>? personContainers; List<PersonContainer>? personContainers;
Dictionary<int, List<PersonContainer>>? idTo; Dictionary<int, List<PersonContainer>>? idTo;
int? linkedAlphaCheck = string.IsNullOrEmpty(configuration.LinkedAlpha) ? null : configuration.LinkedAlpha[0] - 65;
if (personKeyFormattedIdThenWholePercentagesCollection.Count > 0) if (personKeyFormattedIdThenWholePercentagesCollection.Count > 0)
{ {
foreach (PersonKeyFormattedIdThenWholePercentages personKeyFormattedIdThenWholePercentages in personKeyFormattedIdThenWholePercentagesCollection) foreach (PersonKeyFormattedIdThenWholePercentages personKeyFormattedIdThenWholePercentages in personKeyFormattedIdThenWholePercentagesCollection)
@ -312,6 +314,13 @@ internal abstract class MapLogic
personBirthday = IPersonBirthday.GetPersonBirthday(configuration.PersonBirthdayFormat, personKeyFormattedIdThenWholePercentages.PersonKeyFormatted); personBirthday = IPersonBirthday.GetPersonBirthday(configuration.PersonBirthdayFormat, personKeyFormattedIdThenWholePercentages.PersonKeyFormatted);
if (personBirthday is null) if (personBirthday is null)
throw new Exception(); throw new Exception();
if (linkedAlphaCheck is not null && personKeyFormattedIdThenWholePercentages.LinksCount is not null && personKeyFormattedIdThenWholePercentages.LinksCount.Value < linkedAlphaCheck.Value)
{
if (!skipCollection.ContainsKey(personKeyFormattedIdThenWholePercentages.Id))
skipCollection.Add(personKeyFormattedIdThenWholePercentages.Id, []);
skipCollection[personKeyFormattedIdThenWholePercentages.Id].Add((personKeyFormattedIdThenWholePercentages.MappedFaceFilePath.FullName, personKeyFormattedIdThenWholePercentages.WholePercentages));
continue;
}
if (!personKeyFormattedToPersonContainer.TryGetValue(personKeyFormattedIdThenWholePercentages.PersonKeyFormatted, out personContainer)) if (!personKeyFormattedToPersonContainer.TryGetValue(personKeyFormattedIdThenWholePercentages.PersonKeyFormatted, out personContainer))
throw new Exception(); throw new Exception();
if (!results.TryGetValue(personKeyFormattedIdThenWholePercentages.Id, out idTo)) if (!results.TryGetValue(personKeyFormattedIdThenWholePercentages.Id, out idTo))
@ -457,7 +466,7 @@ internal abstract class MapLogic
} }
if (!filePath.Name.EndsWith(".dup") && !filePath.Name.EndsWith(".unk") && !filePath.Name.EndsWith(".abd")) if (!filePath.Name.EndsWith(".dup") && !filePath.Name.EndsWith(".unk") && !filePath.Name.EndsWith(".abd"))
continue; continue;
if (!File.Exists(filePath.Name)) if (!File.Exists(filePath.FullName))
continue; continue;
checkFile = filePath.FullName[..^4]; checkFile = filePath.FullName[..^4];
if (File.Exists(checkFile)) if (File.Exists(checkFile))
@ -470,7 +479,7 @@ internal abstract class MapLogic
return results; return results;
} }
private static void ParallelFor(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, Dictionary<int, List<(string, int)>> skipCollection, List<LocationContainer> locationContainers, MappedFile mappedFile) private static void ParallelFor(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, ReadOnlyDictionary<int, List<(string, int)>> skipCollection, List<LocationContainer> locationContainers, MappedFile mappedFile)
{ {
int? id; int? id;
string checkFile; string checkFile;
@ -502,7 +511,7 @@ internal abstract class MapLogic
} }
if (wholePercentages is null) if (wholePercentages is null)
return; return;
if (string.IsNullOrEmpty(configuration.LocationContainerDebugDirectory) && skipCollection.TryGetValue(id.Value, out wholePercentagesCollection)) if (configuration.LinkedAlpha is null && string.IsNullOrEmpty(configuration.LocationContainerDebugDirectory) && skipCollection.TryGetValue(id.Value, out wholePercentagesCollection))
{ {
fileMatches = (from l in wholePercentagesCollection where l.WholePercentages == wholePercentages select l.File).ToArray(); fileMatches = (from l in wholePercentagesCollection where l.WholePercentages == wholePercentages select l.File).ToArray();
foreach (string fileMatch in fileMatches) foreach (string fileMatch in fileMatches)
@ -734,11 +743,11 @@ internal abstract class MapLogic
} }
} }
internal static ReadOnlyDictionary<int, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>> GetIdThenWholePercentagesToPersonContainers(Configuration configuration, ReadOnlyDictionary<string, PersonContainer> personKeyFormattedToPersonContainer, ReadOnlyCollection<PersonKeyFormattedIdThenWholePercentages> personKeyFormattedIdThenWholePercentagesCollection) internal static ReadOnlyDictionary<int, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>> GetIdThenWholePercentagesToPersonContainers(Configuration configuration, Dictionary<int, List<(string, int)>> skipCollection, ReadOnlyDictionary<string, PersonContainer> personKeyFormattedToPersonContainer, ReadOnlyCollection<PersonKeyFormattedIdThenWholePercentages> personKeyFormattedIdThenWholePercentagesCollection)
{ {
ReadOnlyDictionary<int, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>> results; ReadOnlyDictionary<int, ReadOnlyDictionary<int, ReadOnlyCollection<PersonContainer>>> results;
Dictionary<int, Dictionary<int, List<PersonContainer>>> idThenWholePercentagesToPersonContainerCollection; Dictionary<int, Dictionary<int, List<PersonContainer>>> idThenWholePercentagesToPersonContainerCollection;
idThenWholePercentagesToPersonContainerCollection = GetAll(configuration, personKeyFormattedToPersonContainer, personKeyFormattedIdThenWholePercentagesCollection); idThenWholePercentagesToPersonContainerCollection = GetAll(configuration, skipCollection, personKeyFormattedToPersonContainer, personKeyFormattedIdThenWholePercentagesCollection);
results = GetReadOnly(idThenWholePercentagesToPersonContainerCollection); results = GetReadOnly(idThenWholePercentagesToPersonContainerCollection);
return results; return results;
} }
@ -766,7 +775,7 @@ internal abstract class MapLogic
wholePercentagesCollection = idToWholePercentagesCollection[record.MappedFaceFilePath.Id.Value]; wholePercentagesCollection = idToWholePercentagesCollection[record.MappedFaceFilePath.Id.Value];
wholePercentagesCollection.Add(wholePercentages.Value); wholePercentagesCollection.Add(wholePercentages.Value);
idToWholePercentagesCollection[record.MappedFaceFilePath.Id.Value].Add(wholePercentages.Value); idToWholePercentagesCollection[record.MappedFaceFilePath.Id.Value].Add(wholePercentages.Value);
results.Add(new(record.PersonKeyFormatted, record.PersonDisplayDirectoryName, record.IsDefault, record.MappedFaceFilePath, record.MappedFaceFilePath.Id.Value, wholePercentages.Value)); results.Add(new(record.PersonKeyFormatted, record.PersonDisplayDirectoryName, record.IsDefault, record.LinksCount, record.MappedFaceFilePath, record.MappedFaceFilePath.Id.Value, wholePercentages.Value));
} }
return new(results); return new(results);
} }
@ -890,7 +899,7 @@ internal abstract class MapLogic
} }
} }
internal static List<LocationContainer> GetLocationContainers(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, long ticks, ReadOnlyCollection<PersonContainer> personContainers, Dictionary<int, List<(string, int)>> skipCollection, List<Record> records) internal static List<LocationContainer> GetLocationContainers(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, long ticks, ReadOnlyCollection<PersonContainer> personContainers, ReadOnlyDictionary<int, List<(string, int)>> skipCollection, List<Record> records)
{ {
List<LocationContainer> results = []; List<LocationContainer> results = [];
List<MappedFile> mappedFiles = GetMappedFiles(propertyConfiguration, configuration, personContainers, records); List<MappedFile> mappedFiles = GetMappedFiles(propertyConfiguration, configuration, personContainers, records);

View File

@ -84,7 +84,7 @@ internal abstract class RelationLogic
return new(results); return new(results);
} }
private static ReadOnlyDictionary<string, string> MoveFiles(Configuration configuration, string key, bool isCounterPersonYear, string? displayDirectoryName, ReadOnlyCollection<RelationContainer> relationContainers, List<string> linked1, List<string> linked2, List<string> linked3, List<string> linked4, List<string> linked5, List<string> linked6, List<string> linked7, List<string> linked8, List<string> linked9) private static ReadOnlyDictionary<string, string> MoveFiles(Configuration configuration, string key, bool isCounterPersonYear, string? displayDirectoryName, ReadOnlyCollection<RelationContainer> relationContainers, List<List<string>> linked)
{ {
Dictionary<string, string> results = []; Dictionary<string, string> results = [];
string value; string value;
@ -105,23 +105,55 @@ internal abstract class RelationLogic
maybeTicksDirectoryName = Path.GetFileName(personKeyFormattedDirectory); maybeTicksDirectoryName = Path.GetFileName(personKeyFormattedDirectory);
if (string.IsNullOrEmpty(personNameDirectory) || string.IsNullOrEmpty(yearDirectory) || string.IsNullOrEmpty(personKeyFormattedDirectory) || string.IsNullOrEmpty(personNameDirectoryName)) if (string.IsNullOrEmpty(personNameDirectory) || string.IsNullOrEmpty(yearDirectory) || string.IsNullOrEmpty(personKeyFormattedDirectory) || string.IsNullOrEmpty(personNameDirectoryName))
continue; continue;
if (linked9.Contains(fileHolder.FullName)) if (linked[24].Contains(fileHolder.FullName))
value = "ZZZ";
else if (linked[23].Contains(fileHolder.FullName))
value = "YYY";
else if (linked[22].Contains(fileHolder.FullName))
value = "XXX";
else if (linked[21].Contains(fileHolder.FullName))
value = "WWW";
else if (linked[20].Contains(fileHolder.FullName))
value = "VVV";
else if (linked[19].Contains(fileHolder.FullName))
value = "UUU";
else if (linked[18].Contains(fileHolder.FullName))
value = "TTT";
else if (linked[17].Contains(fileHolder.FullName))
value = "SSS";
else if (linked[16].Contains(fileHolder.FullName))
value = "RRR";
else if (linked[15].Contains(fileHolder.FullName))
value = "QQQ";
else if (linked[14].Contains(fileHolder.FullName))
value = "PPP";
else if (linked[13].Contains(fileHolder.FullName))
value = "OOO";
else if (linked[12].Contains(fileHolder.FullName))
value = "NNN";
else if (linked[11].Contains(fileHolder.FullName))
value = "MMM";
else if (linked[10].Contains(fileHolder.FullName))
value = "LLL";
else if (linked[9].Contains(fileHolder.FullName))
value = "KKK";
else if (linked[8].Contains(fileHolder.FullName))
value = "JJJ"; value = "JJJ";
else if (linked8.Contains(fileHolder.FullName)) else if (linked[7].Contains(fileHolder.FullName))
value = "III"; value = "III";
else if (linked7.Contains(fileHolder.FullName)) else if (linked[6].Contains(fileHolder.FullName))
value = "HHH"; value = "HHH";
else if (linked6.Contains(fileHolder.FullName)) else if (linked[5].Contains(fileHolder.FullName))
value = "GGG"; value = "GGG";
else if (linked5.Contains(fileHolder.FullName)) else if (linked[4].Contains(fileHolder.FullName))
value = "FFF"; value = "FFF";
else if (linked4.Contains(fileHolder.FullName)) else if (linked[3].Contains(fileHolder.FullName))
value = "EEE"; value = "EEE";
else if (linked3.Contains(fileHolder.FullName)) else if (linked[2].Contains(fileHolder.FullName))
value = "DDD"; value = "DDD";
else if (linked2.Contains(fileHolder.FullName)) else if (linked[1].Contains(fileHolder.FullName))
value = "CCC"; value = "CCC";
else if (linked1.Contains(fileHolder.FullName)) else if (linked[0].Contains(fileHolder.FullName))
value = "BBB"; value = "BBB";
else else
value = "AAA"; value = "AAA";
@ -231,67 +263,24 @@ internal abstract class RelationLogic
private static ReadOnlyDictionary<string, string> GetMoveFiles(Configuration configuration, string key, int take, bool isCounterPersonYear, string? displayDirectoryName, ReadOnlyCollection<RelationContainer> relationContainers) private static ReadOnlyDictionary<string, string> GetMoveFiles(Configuration configuration, string key, int take, bool isCounterPersonYear, string? displayDirectoryName, ReadOnlyCollection<RelationContainer> relationContainers)
{ {
ReadOnlyDictionary<string, string> results; ReadOnlyDictionary<string, string> results;
List<string> linked1 = []; List<List<string>> linked = [];
List<string> linked2 = []; for (int i = 0; i < 25; i++)
List<string> linked3 = []; linked.Add([]);
List<string> linked4 = [];
List<string> linked5 = [];
List<string> linked6 = [];
List<string> linked7 = [];
List<string> linked8 = [];
List<string> linked9 = [];
foreach ((FileHolder fileHolder, ReadOnlyCollection<Relation> relations) in relationContainers) foreach ((FileHolder fileHolder, ReadOnlyCollection<Relation> relations) in relationContainers)
{ {
foreach (Relation relation in relations.Take(take)) foreach (Relation relation in relations.Take(take))
{ {
if (!linked1.Contains(relation.File)) for (int i = 0; i < 25; i++)
{ {
linked1.Add(relation.File); if (!linked[i].Contains(relation.File))
continue; {
} linked[i].Add(relation.File);
if (!linked2.Contains(relation.File)) break;
{ }
linked2.Add(relation.File);
continue;
}
if (!linked3.Contains(relation.File))
{
linked3.Add(relation.File);
continue;
}
if (!linked4.Contains(relation.File))
{
linked4.Add(relation.File);
continue;
}
if (!linked5.Contains(relation.File))
{
linked5.Add(relation.File);
continue;
}
if (!linked6.Contains(relation.File))
{
linked6.Add(relation.File);
continue;
}
if (!linked7.Contains(relation.File))
{
linked7.Add(relation.File);
continue;
}
if (!linked8.Contains(relation.File))
{
linked8.Add(relation.File);
continue;
}
if (!linked9.Contains(relation.File))
{
linked9.Add(relation.File);
continue;
} }
} }
} }
results = MoveFiles(configuration, key, isCounterPersonYear, displayDirectoryName, relationContainers, linked1, linked2, linked3, linked4, linked5, linked6, linked7, linked8, linked9); results = MoveFiles(configuration, key, isCounterPersonYear, displayDirectoryName, relationContainers, linked);
return results; return results;
} }

View File

@ -60,8 +60,8 @@ public class MetadataQuery
private List<(string FileName, string TagGroup, string TagIdName, string Value)> GetCollection(long ticks) private List<(string FileName, string TagGroup, string TagIdName, string Value)> GetCollection(long ticks)
{ {
string json; string json;
string model; string? model;
string maker; string? maker;
string message; string message;
FileInfo fileInfo; FileInfo fileInfo;
ProgressBar progressBar; ProgressBar progressBar;

View File

@ -5,7 +5,7 @@ namespace View_by_Distance.Metadata.Models.Stateless.Methods;
internal static class Base internal static class Base
{ {
internal static string GetMaker(ExifDirectoryBase[]? exifBaseDirectories) internal static string? GetMaker(ExifDirectoryBase[]? exifBaseDirectories)
{ {
string? result = null; string? result = null;
if (exifBaseDirectories is not null) if (exifBaseDirectories is not null)
@ -23,12 +23,10 @@ internal static class Base
} }
} }
} }
if (string.IsNullOrEmpty(result))
result = "Unknown";
return result; return result;
} }
internal static string GetModel(ExifDirectoryBase[]? exifBaseDirectories) internal static string? GetModel(ExifDirectoryBase[]? exifBaseDirectories)
{ {
string? result = null; string? result = null;
if (exifBaseDirectories is not null) if (exifBaseDirectories is not null)
@ -46,8 +44,6 @@ internal static class Base
} }
} }
} }
if (string.IsNullOrEmpty(result))
result = "Unknown";
return result; return result;
} }

View File

@ -19,14 +19,14 @@ public interface IMetadata
static ExifDirectory GetExifDirectory(FilePath filePath) => static ExifDirectory GetExifDirectory(FilePath filePath) =>
Exif.GetExifDirectory(filePath); Exif.GetExifDirectory(filePath);
string TestStatic_GetMaker(ExifDirectory? exifDirectory) => string? TestStatic_GetMaker(ExifDirectory? exifDirectory) =>
GetMaker(exifDirectory); GetMaker(exifDirectory);
static string GetMaker(ExifDirectory? exifDirectory) => static string? GetMaker(ExifDirectory? exifDirectory) =>
Base.GetMaker(exifDirectory?.ExifBaseDirectories); Base.GetMaker(exifDirectory?.ExifBaseDirectories);
string TestStatic_GetModel(ExifDirectory? exifDirectory) => string? TestStatic_GetModel(ExifDirectory? exifDirectory) =>
GetModel(exifDirectory); GetModel(exifDirectory);
static string GetModel(ExifDirectory? exifDirectory) => static string? GetModel(ExifDirectory? exifDirectory) =>
Base.GetModel(exifDirectory?.ExifBaseDirectories); Base.GetModel(exifDirectory?.ExifBaseDirectories);
string? TestStatic_GetOutputResolution(ExifDirectory? exifDirectory) => string? TestStatic_GetOutputResolution(ExifDirectory? exifDirectory) =>

View File

@ -402,7 +402,7 @@ public class Rename
{ {
if (record.Id is null) if (record.Id is null)
continue; continue;
paddedId = IId.GetPaddedId(_PropertyConfiguration, record.Index, record.Id.Value); paddedId = IId.GetPaddedId(_PropertyConfiguration, record.Id.Value, record.Index);
checkFileExtension = fileHolder.ExtensionLowered == jpeg ? jpg : fileHolder.ExtensionLowered; checkFileExtension = fileHolder.ExtensionLowered == jpeg ? jpg : fileHolder.ExtensionLowered;
checkFile = Path.Combine(seasonDirectory, $"{paddedId}{checkFileExtension}"); checkFile = Path.Combine(seasonDirectory, $"{paddedId}{checkFileExtension}");
if (checkFile == fileHolder.FullName) if (checkFile == fileHolder.FullName)

View File

@ -14,6 +14,9 @@ public record MappingFromFilterPre(bool? InSkipCollection,
return result; return result;
} }
internal static void Constructor() =>
_ = new MappingFromFilterPre(null, null, null);
} }
[JsonSourceGenerationOptions(WriteIndented = true)] [JsonSourceGenerationOptions(WriteIndented = true)]

View File

@ -194,11 +194,11 @@ internal abstract class Container
return (count, results); return (count, results);
} }
internal static List<int> GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers) internal static List<int> GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers)
{ {
List<int> results = []; List<int> results = [];
Models.Item[] filteredItems; Models.Item[] filteredItems;
foreach (Models.Container container in containers) foreach (Models.Container container in readOnlyContainers)
{ {
if (container.Items.Count == 0) if (container.Items.Count == 0)
continue; continue;

View File

@ -25,10 +25,10 @@ public interface IContainer
static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<string[]> filesCollection) => static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection<string[]> filesCollection) =>
Container.GetContainers(propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filesCollection); Container.GetContainers(propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filesCollection);
List<int> TestStatic_GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers) => List<int> TestStatic_GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
GetFilteredDistinctIds(propertyConfiguration, containers); GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers);
static List<int> GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers) => static List<int> GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> readOnlyContainers) =>
Container.GetFilteredDistinctIds(propertyConfiguration, containers); Container.GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers);
ReadOnlyCollection<Models.Item> TestStatic_GetItems(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> containers, bool distinctItems, bool filterItems) => ReadOnlyCollection<Models.Item> TestStatic_GetItems(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection<Models.Container> containers, bool distinctItems, bool filterItems) =>
GetItems(propertyConfiguration, containers, distinctItems, filterItems); GetItems(propertyConfiguration, containers, distinctItems, filterItems);

View File

@ -13,10 +13,10 @@ public interface IId
static int GetId(Properties.IPropertyConfiguration propertyConfiguration, string intelligentId) => static int GetId(Properties.IPropertyConfiguration propertyConfiguration, string intelligentId) =>
Id.GetId(propertyConfiguration, intelligentId); Id.GetId(propertyConfiguration, intelligentId);
string TestStatic_GetPaddedId(Properties.IPropertyConfiguration propertyConfiguration, int index, int id) => string TestStatic_GetPaddedId(Properties.IPropertyConfiguration propertyConfiguration, int id, int? index) =>
GetPaddedId(propertyConfiguration, index, id); GetPaddedId(propertyConfiguration, id, index);
static string GetPaddedId(Properties.IPropertyConfiguration propertyConfiguration, int index, int id) => static string GetPaddedId(Properties.IPropertyConfiguration propertyConfiguration, int id, int? index) =>
Id.GetPaddedId(propertyConfiguration, index, id); Id.GetPaddedId(propertyConfiguration, id, index);
bool TestStatic_IsIgnore(FilePath filePath) => bool TestStatic_IsIgnore(FilePath filePath) =>
IsIgnore(filePath); IsIgnore(filePath);

View File

@ -62,14 +62,19 @@ internal abstract class Id
return result; return result;
} }
internal static string GetPaddedId(Properties.IPropertyConfiguration propertyConfiguration, int index, int id) internal static string GetPaddedId(Properties.IPropertyConfiguration propertyConfiguration, int id, int? index)
{ {
string result; string result;
string intelligentId = GetIntelligentId(propertyConfiguration, id, ignore: false); if (propertyConfiguration.Offset < 0)
int check = GetId(propertyConfiguration, intelligentId); result = Guid.NewGuid().ToString();
if (check != id) else
throw new NotSupportedException(); {
result = $"{propertyConfiguration.Offset + index}{intelligentId}"; string intelligentId = GetIntelligentId(propertyConfiguration, id, ignore: false);
int check = GetId(propertyConfiguration, intelligentId);
if (check != id)
throw new NotSupportedException();
result = index is null || propertyConfiguration.Offset == 9876543 ? intelligentId : $"{propertyConfiguration.Offset + index}{intelligentId}";
}
return result; return result;
} }

View File

@ -324,7 +324,7 @@ internal abstract partial class XDirectory
} }
if (ifCanUseId && filePath.IsIntelligentIdFormat && filePath.Id is not null && filePath.DirectoryName is not null) if (ifCanUseId && filePath.IsIntelligentIdFormat && filePath.Id is not null && filePath.DirectoryName is not null)
{ {
paddedId = IId.GetPaddedId(propertyConfiguration, i, filePath.Id.Value); paddedId = IId.GetPaddedId(propertyConfiguration, filePath.Id.Value, i);
paddedIdFile = Path.Combine(filePath.DirectoryName, $"{paddedId}{filePath.ExtensionLowered}"); paddedIdFile = Path.Combine(filePath.DirectoryName, $"{paddedId}{filePath.ExtensionLowered}");
if (!File.Exists(paddedIdFile)) if (!File.Exists(paddedIdFile))
{ {