From 4081a73b9dc0802f15d61e47b38218ff8d696ec9 Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Sat, 27 Jan 2024 18:11:24 -0700 Subject: [PATCH] Work with video --- Distance/Models/_E_Distance.cs | 3 +- Duplicate-Search/DuplicateSearch.cs | 4 +- Instance/DlibDotNet.cs | 94 +++++++------- Instance/Models/Binder/Configuration.cs | 3 + Instance/Models/Configuration.cs | 1 + Map/Models/Configuration.cs | 1 + Map/Models/MapLogic.cs | 13 +- Map/Models/Stateless/DistanceLogic.cs | 52 ++++++-- Map/Models/Stateless/MapLogic.cs | 25 ++-- Map/Models/Stateless/RelationLogic.cs | 115 ++++++++---------- Metadata-Query/MetadataQuery.cs | 4 +- Metadata/Models/Stateless/Base.cs | 8 +- .../Models/Stateless/Methods/IMetadata.cs | 8 +- Rename/Rename.cs | 2 +- Shared/Models/MappingFromFilterPre.cs | 3 + Shared/Models/Stateless/Methods/Container.cs | 4 +- Shared/Models/Stateless/Methods/IContainer.cs | 8 +- Shared/Models/Stateless/Methods/IId.cs | 8 +- Shared/Models/Stateless/Methods/Id.cs | 17 ++- Shared/Models/Stateless/Methods/XDirectory.cs | 2 +- 20 files changed, 210 insertions(+), 165 deletions(-) diff --git a/Distance/Models/_E_Distance.cs b/Distance/Models/_E_Distance.cs index 3ab6b1c..2b9b8f5 100644 --- a/Distance/Models/_E_Distance.cs +++ b/Distance/Models/_E_Distance.cs @@ -431,7 +431,8 @@ public partial class E_Distance : IDistance if (faceDistanceContainer.Face.Mapping.MappingFromLocation.AreaPermyriad < distanceLimits.FaceAreaPermyriad) continue; 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) continue; if (faceDistanceContainer.Face.Mapping.MappingFromFilterPre.IsFocusRelativePath is not null && !faceDistanceContainer.Face.Mapping.MappingFromFilterPre.IsFocusRelativePath.Value) diff --git a/Duplicate-Search/DuplicateSearch.cs b/Duplicate-Search/DuplicateSearch.cs index 97e8cea..2231205 100644 --- a/Duplicate-Search/DuplicateSearch.cs +++ b/Duplicate-Search/DuplicateSearch.cs @@ -29,9 +29,9 @@ public class DuplicateSearch else { Configuration.Verify(configuration, requireExist: false); + Container[] containers = GetContainers(ticks, configuration); string argZero = args.Count > 0 ? Path.GetFullPath(args[0]) : Path.GetFullPath(configuration.RootDirectory); bool argZeroIsConfigurationRootDirectory = configuration.RootDirectory == argZero; - Container[] containers = GetContainers(appSettings, ticks, argZero, configuration, argZeroIsConfigurationRootDirectory); string destinationRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(configuration, "Z) Moved"); List preloadIds = GetPreloadIds(destinationRoot); Dictionary> 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; Container[] containers; diff --git a/Instance/DlibDotNet.cs b/Instance/DlibDotNet.cs index 4f24660..a10b8ad 100644 --- a/Instance/DlibDotNet.cs +++ b/Instance/DlibDotNet.cs @@ -278,7 +278,6 @@ public partial class DlibDotNet ReadOnlyDictionary> personKeyToIds; ReadOnlyCollection? filesCollection = null; bool runToDoCollectionFirst = GetRunToDoCollectionFirst(ticks); - Dictionary> fileNameToCollection; (aResultsFullGroupDirectory, bResultsFullGroupDirectory) = GetResultsFullGroupDirectories(); ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; 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); progressBar.Tick(); } - fileNameToCollection = !Directory.Exists(fPhotoPrismSingletonDirectory) ? fileNameToCollection = [] : F_PhotoPrism.GetFileNameToCollection(fPhotoPrismSingletonDirectory); - B_Metadata metadata = new(_Configuration.PropertyConfiguration, _Configuration.ForceMetadataLastWriteTimeToCreationTime, _Configuration.PropertiesChangedForMetadata, bResultsFullGroupDirectory); + ReadOnlyCollection readOnlyContainers = new(containers); + SaveDistinctIds(_Configuration.PropertyConfiguration, bResultsFullGroupDirectory, readOnlyContainers); 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); - ReadOnlyCollection distinctFilteredItems = Shared.Models.Stateless.Methods.IContainer.GetItems(_Configuration.PropertyConfiguration, new(containers), distinctItems: true, filterItems: true); + FullDoWork(argZero, propertyRoot, ticks, aResultsFullGroupDirectory, bResultsFullGroupDirectory, fPhotoPrismSingletonDirectory, t, readOnlyContainers, propertyLogic, mapLogic); + ReadOnlyCollection distinctFilteredItems = Shared.Models.Stateless.Methods.IContainer.GetItems(_Configuration.PropertyConfiguration, readOnlyContainers, distinctItems: true, filterItems: true); if (_Configuration.LookForAbandoned) { string dResultsFullGroupDirectory; @@ -362,12 +361,12 @@ public partial class DlibDotNet foreach (string outputResolution in _Configuration.OutputResolutions) { (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(); ReadOnlyCollection distinctFilteredFaces = Map.Models.Stateless.Methods.IMapLogic.GetFaces(distinctFilteredItems); - ReadOnlyCollection distinctFilteredMappingCollection = GetMappings(_Configuration.PropertyConfiguration, eDistanceContentDirectory, containers, mapLogic, distinctItems: true); + ReadOnlyCollection distinctFilteredMappingCollection = GetMappings(_Configuration.PropertyConfiguration, eDistanceContentDirectory, readOnlyContainers, mapLogic, distinctItems: true); if (runToDoCollectionFirst) { if (!Directory.Exists(eDistanceContentDirectory)) @@ -391,7 +390,7 @@ public partial class DlibDotNet && outputResolution == _Configuration.OutputResolutions[0] && _Configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions.Contains(outputResolution) && _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) _Random.Random(_Configuration.PropertyConfiguration, _Configuration.RadomUseBirthdayMinimum, _Configuration.ValidKeyWordsToIgnoreInRandom, outputResolution, personKeyToIds, notNineCollection, distinctFilteredMappingCollection); if (_IsEnvironment.Development) @@ -509,7 +508,7 @@ public partial class DlibDotNet 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> fileNameToCollection, MapLogic mapLogic) + private void FullDoWork(string argZero, string propertyRoot, long ticks, string aResultsFullGroupDirectory, string bResultsFullGroupDirectory, string fPhotoPrismSingletonDirectory, int t, ReadOnlyCollection readOnlyContainers, A_Property propertyLogic, MapLogic mapLogic) { int total; int notMapped; @@ -525,10 +524,12 @@ public partial class DlibDotNet string dResultsFullGroupDirectory; string c2ResultsFullGroupDirectory; string d2ResultsFullGroupDirectory; - int containersLength = containers.Length; + int containersLength = readOnlyContainers.Count; List> sourceDirectoryChanges = []; int maxDegreeOfParallelism = _AppSettings.MaxDegreeOfParallelism; + Dictionary> fileNameToCollection = !Directory.Exists(fPhotoPrismSingletonDirectory) ? fileNameToCollection = [] : F_PhotoPrism.GetFileNameToCollection(fPhotoPrismSingletonDirectory); 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) { total = 0; @@ -538,9 +539,9 @@ public partial class DlibDotNet _Resize.Update(cResultsFullGroupDirectory); _FaceParts.Update(d2ResultsFullGroupDirectory); _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) continue; if (!_ArgZeroIsConfigurationRootDirectory && !container.SourceDirectory.StartsWith(argZero)) @@ -595,21 +596,45 @@ public partial class DlibDotNet } } - private ReadOnlyCollection GetMappings(Property.Models.Configuration propertyConfiguration, string eDistanceContentDirectory, Container[] containers, MapLogic mapLogic, bool distinctItems) + private static void SaveDistinctIds(Property.Models.Configuration propertyConfiguration, string bResultsFullGroupDirectory, ReadOnlyCollection readOnlyContainers) + { + List 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 GetMappings(Property.Models.Configuration propertyConfiguration, string eDistanceContentDirectory, ReadOnlyCollection readOnlyContainers, MapLogic mapLogic, bool distinctItems) { ReadOnlyCollection results; int count = 0; int notMapped; Mapping mapping; bool anyValidFaces; + List distinct = []; string focusRelativePath; bool? isFocusRelativePath; - List distinct = []; DateTime[] containerDateTimes; IEnumerable filteredItems; MappingFromItem mappingFromItem; List mappingCollection = []; - foreach (Container container in containers) + foreach (Container container in readOnlyContainers) { if (container.Items.Count == 0) continue; @@ -858,6 +883,7 @@ public partial class DlibDotNet configuration.DistanceRenameToMatch, configuration.FaceConfidencePercent, configuration.FaceDistancePermyriad, + configuration.LinkedAlpha, configuration.LocationContainerDebugDirectory, configuration.LocationContainerDirectoryPattern, configuration.LocationContainerDistanceGroupMinimum, @@ -885,41 +911,21 @@ public partial class DlibDotNet private (Mapping, int) GetMappingAndUpdateMappingFromPerson(MapLogic mapLogic, Item item, bool? isFocusRelativePath, MappingFromItem mappingFromItem) { Mapping result; - bool? canReMap; int? eyeα = null; - bool? isFocusPerson; bool? eyeReview = null; - bool? inSkipCollection; int confidencePercent = 0; int faceAreaPermyriad = 0; - int wholePercentRectangle; - string deterministicHashCodeKey; - MappingFromLocation? mappingFromLocation; - MappingFromFilterPre mappingFromFilterPre; - MappingFromFilterPost mappingFromFilterPost; bool? isFocusModel = GetIsFocusModel(item.Property); long[] jLinkResolvedPersonKeys = _JLinkResolvedDirectories.Select(l => l.PersonKey).ToArray(); - ReadOnlyDictionary>? wholePercentagesToPersonContainers = mapLogic.GetWholePercentagesToPersonContainers(item.Property?.Id); - if (item.Property?.Id is null) - { - canReMap = null; - isFocusPerson = null; - inSkipCollection = null; - mappingFromLocation = null; - mappingFromFilterPost = new(canReMap, inSkipCollection, isFocusPerson); - mappingFromFilterPre = new(inSkipCollection, isFocusModel, isFocusRelativePath); - } - 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); - } + ReadOnlyDictionary>? wholePercentagesToPersonContainers = mapLogic.GetWholePercentagesToPersonContainers(mappingFromItem.Id); + int wholePercentRectangle = Shared.Models.Stateless.Methods.ILocation.GetWholePercentages(Shared.Models.Stateless.ILocation.Digits); + string deterministicHashCodeKey = IMapping.GetDeterministicHashCodeKey(item.FilePath, Shared.Models.Stateless.ILocation.Digits); + MappingFromLocation? mappingFromLocation = new(faceAreaPermyriad, confidencePercent, deterministicHashCodeKey, eyeα, eyeReview, wholePercentRectangle); + bool? inSkipCollection = mapLogic.InSkipCollection(mappingFromItem.Id, mappingFromLocation); + MappingFromFilterPre mappingFromFilterPre = new(inSkipCollection, isFocusModel, isFocusRelativePath); + bool? canReMap = Map.Models.Stateless.Methods.IMapLogic.CanReMap(jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation); + bool? isFocusPerson = mapLogic.IsFocusPerson(_Configuration.SkipPersonWithMoreThen, jLinkResolvedPersonKeys, wholePercentagesToPersonContainers, mappingFromLocation); + MappingFromFilterPost mappingFromFilterPost = new(canReMap, inSkipCollection, isFocusPerson); result = new(item.FilePath, mappingFromFilterPost, mappingFromFilterPre, mappingFromItem, mappingFromLocation, mappingFromPhotoPrismCollection: null); int notMapped = mapLogic.UpdateMappingFromPerson(wholePercentagesToPersonContainers, result); return (result, notMapped); diff --git a/Instance/Models/Binder/Configuration.cs b/Instance/Models/Binder/Configuration.cs index 43e8567..38cac67 100644 --- a/Instance/Models/Binder/Configuration.cs +++ b/Instance/Models/Binder/Configuration.cs @@ -29,6 +29,7 @@ public class Configuration public string? GenealogicalDataCommunicationFile { get; set; } public string[]? IgnoreExtensions { get; set; } public string[]? JLinks { get; set; } + public string? LinkedAlpha { get; set; } public string[]? LoadOrCreateThenSaveDistanceResultsForOutputResolutions { get; set; } public string[]? LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { 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?.IgnoreExtensions is null) throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); // 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?.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions)); if (configuration?.LoadPhotoPrismLocations is null) throw new NullReferenceException(nameof(configuration.LoadPhotoPrismLocations)); @@ -220,6 +222,7 @@ public class Configuration configuration.GenealogicalDataCommunicationFile, configuration.IgnoreExtensions ?? [], configuration.JLinks ?? [], + configuration.LinkedAlpha, configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions ?? [], configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions ?? [], configuration.LoadPhotoPrismLocations.Value, diff --git a/Instance/Models/Configuration.cs b/Instance/Models/Configuration.cs index 2e43b18..bf8397f 100644 --- a/Instance/Models/Configuration.cs +++ b/Instance/Models/Configuration.cs @@ -23,6 +23,7 @@ public record Configuration(Property.Models.Configuration PropertyConfiguration, string GenealogicalDataCommunicationFile, string[] IgnoreExtensions, string[] JLinks, + string? LinkedAlpha, string[] LoadOrCreateThenSaveDistanceResultsForOutputResolutions, string[] LoadOrCreateThenSaveImageFacesResultsForOutputResolutions, bool LoadPhotoPrismLocations, diff --git a/Map/Models/Configuration.cs b/Map/Models/Configuration.cs index afbf9af..96280f3 100644 --- a/Map/Models/Configuration.cs +++ b/Map/Models/Configuration.cs @@ -5,6 +5,7 @@ public record Configuration(bool DeletePossibleDuplicates, bool DistanceRenameToMatch, int FaceConfidencePercent, int FaceDistancePermyriad, + string? LinkedAlpha, string LocationContainerDebugDirectory, string LocationContainerDirectoryPattern, int LocationContainerDistanceGroupMinimum, diff --git a/Map/Models/MapLogic.cs b/Map/Models/MapLogic.cs index 7fc33f2..442be06 100644 --- a/Map/Models/MapLogic.cs +++ b/Map/Models/MapLogic.cs @@ -225,11 +225,12 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic _Ticks = ticks; _Configuration = configuration; _PropertyConfiguration = propertyConfiguration; - ReadOnlyDictionary readOnlyPersonKeyToCount; + List locationContainers = []; List notMappedPersonContainers = []; + ReadOnlyDictionary readOnlyPersonKeyToCount; Dictionary> skipCollection = []; Dictionary> skipNotSkipCollection = []; - List locationContainers = []; + ReadOnlyDictionary> readOnlyskipCollection; string? rootDirectoryParent = Path.GetDirectoryName(propertyConfiguration.RootDirectory); string eDistanceContentTicksDirectory = Path.Combine(eDistanceContentDirectory, ticks.ToString()); ReadOnlyDictionary>> idThenWholePercentagesToPersonContainers; @@ -293,8 +294,10 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic readOnlyPersonKeyToCount, readOnlyPossiblyNewPersonDisplayDirectoryNamesAndPersonContainer); idThenWholePercentagesToPersonContainers = Stateless.MapLogic.GetIdThenWholePercentagesToPersonContainers(configuration, + skipCollection, readOnlyPersonKeyFormattedToPersonContainer, personKeyFormattedIdThenWholePercentagesCollection); + readOnlyskipCollection = new(skipCollection); notMappedPersonContainers.AddRange(Stateless.MapLogic.GetNotMappedPersonContainers(configuration, ticks, personContainers, @@ -304,7 +307,7 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic configuration, ticks, personContainers, - skipCollection, + readOnlyskipCollection, records)); int lossCount = records.Count - locationContainers.Count; int unableToMatchCount = records.Count - personKeyFormattedIdThenWholePercentagesCollection.Count; @@ -1335,11 +1338,11 @@ public partial class MapLogic : Shared.Models.Methods.IMapLogic 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 readOnlyContainers, string cResultsFullGroupDirectory, string dResultsFullGroupDirectory, string d2ResultsFullGroupDirectory) { string[] directories; string? directoryName; - List distinctFilteredIds = IContainer.GetFilteredDistinctIds(propertyConfiguration, containers); + List distinctFilteredIds = IContainer.GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers); LookForAbandoned(propertyConfiguration, distinctFilteredIds); Stateless.LookForAbandonedLogic.LookForAbandoned(propertyConfiguration, bResultsFullGroupDirectory, distinctFilteredIds); directories = Directory.GetDirectories(cResultsFullGroupDirectory, "*", SearchOption.TopDirectoryOnly); diff --git a/Map/Models/Stateless/DistanceLogic.cs b/Map/Models/Stateless/DistanceLogic.cs index 8bef1d7..ff418a8 100644 --- a/Map/Models/Stateless/DistanceLogic.cs +++ b/Map/Models/Stateless/DistanceLogic.cs @@ -9,19 +9,21 @@ using View_by_Distance.Shared.Models.Stateless.Methods; namespace View_by_Distance.Map.Models.Stateless; -internal record Record(string PersonKeyFormatted, - int DirectoryNumber, - string? PersonDisplayDirectoryName, +internal record Record(int DirectoryNumber, bool? IsDefault, - FilePath MappedFaceFilePath); + int? LinksCount, + FilePath MappedFaceFilePath, + string? PersonDisplayDirectoryName, + string PersonKeyFormatted); internal abstract class DistanceLogic { - internal record TicksDirectory(string Directory, - string DirectoryName, + internal record TicksDirectory(DateTime AlternateDirectoryDateTime, + string Directory, DateTime DirectoryDateTime, - DateTime AlternateDirectoryDateTime, + string DirectoryName, + bool? IsLocationContainerDebugDirectory, float? TotalDays); 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; long? lastDirectoryTicks = null; DateTime dateTime = DateTime.Now; + DateTime alternateDirectoryDateTime; + bool? isLocationContainerDebugDirectory; long month = dateTime.AddMonths(1).Ticks - dateTime.Ticks; for (int i = 1; i < 5; i++) _ = IPath.DeleteEmptyDirectories(eDistanceContentDirectory); @@ -125,8 +129,10 @@ internal abstract class DistanceLogic Directory.SetCreationTime(ticksDirectory, new DateTime(directoryTicks)); if (directoryInfo.LastWriteTime.Ticks != 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; - 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) continue; lastDirectoryTicks = directoryTicks; @@ -210,7 +216,7 @@ internal abstract class DistanceLogic } } - private static List GetRecords(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, bool? isDefault, string[] files, int directoryNumber, string personKeyFormatted, List distinct, string? personDisplayDirectoryName) + private static List GetRecords(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, bool? isDefault, string[] files, int directoryNumber, string personKeyFormatted, int? linksCount, List distinct, string? personDisplayDirectoryName) { List results = []; string fileName; @@ -239,7 +245,7 @@ internal abstract class DistanceLogic continue; } distinct.Add(fileName); - results.Add(new(personKeyFormatted, directoryNumber, personDisplayDirectoryName, isDefault, filePath)); + results.Add(new(directoryNumber, isDefault, linksCount, filePath, personDisplayDirectoryName, personKeyFormatted)); } return results; } @@ -263,6 +269,23 @@ internal abstract class DistanceLogic 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 DeleteEmptyDirectoriesAndGetCollection(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, long ticks, string eDistanceContentDirectory, ReadOnlyDictionary personKeyFormattedToNewestPersonKeyFormatted, ReadOnlyCollection personKeyFormattedCollection) { List results = []; @@ -270,6 +293,7 @@ internal abstract class DistanceLogic string message; string[] files; bool? isDefault; + int? linksCount; int totalSeconds; DateTime dateTime; TimeSpan timeSpan; @@ -327,6 +351,10 @@ internal abstract class DistanceLogic { if (check && !Directory.Exists(yearDirectory)) continue; + if (ticksDirectory.IsLocationContainerDebugDirectory is null || !ticksDirectory.IsLocationContainerDebugDirectory.Value) + linksCount = null; + else + linksCount = GetLinksCount(yearDirectory); if (ticksDirectory.DirectoryName != configuration.LocationContainerDebugDirectory) { files = Directory.GetFiles(yearDirectory, "*", SearchOption.TopDirectoryOnly); @@ -338,7 +366,7 @@ internal abstract class DistanceLogic isDefault = null; personDisplayDirectoryName = null; 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); foreach (string file in files) File.Delete(file); @@ -426,7 +454,7 @@ internal abstract class DistanceLogic Directory.Move(personNameDirectory, personFirstInitialDirectory); 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); foreach (string personNameLinkDirectory in personNameLinkDirectories) { diff --git a/Map/Models/Stateless/MapLogic.cs b/Map/Models/Stateless/MapLogic.cs index 713658b..ccd1fcc 100644 --- a/Map/Models/Stateless/MapLogic.cs +++ b/Map/Models/Stateless/MapLogic.cs @@ -27,6 +27,7 @@ internal abstract class MapLogic internal record PersonKeyFormattedIdThenWholePercentages(string PersonKeyFormatted, string? PersonDisplayDirectoryName, bool? IsDefault, + int? LinksCount, FilePath MappedFaceFilePath, int Id, int WholePercentages); @@ -298,13 +299,14 @@ internal abstract class MapLogic return results; } - private static Dictionary>> GetAll(Configuration configuration, ReadOnlyDictionary personKeyFormattedToPersonContainer, ReadOnlyCollection personKeyFormattedIdThenWholePercentagesCollection) + private static Dictionary>> GetAll(Configuration configuration, Dictionary> skipCollection, ReadOnlyDictionary personKeyFormattedToPersonContainer, ReadOnlyCollection personKeyFormattedIdThenWholePercentagesCollection) { Dictionary>> results = []; PersonBirthday? personBirthday; PersonContainer? personContainer; List? personContainers; Dictionary>? idTo; + int? linkedAlphaCheck = string.IsNullOrEmpty(configuration.LinkedAlpha) ? null : configuration.LinkedAlpha[0] - 65; if (personKeyFormattedIdThenWholePercentagesCollection.Count > 0) { foreach (PersonKeyFormattedIdThenWholePercentages personKeyFormattedIdThenWholePercentages in personKeyFormattedIdThenWholePercentagesCollection) @@ -312,6 +314,13 @@ internal abstract class MapLogic personBirthday = IPersonBirthday.GetPersonBirthday(configuration.PersonBirthdayFormat, personKeyFormattedIdThenWholePercentages.PersonKeyFormatted); if (personBirthday is null) 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)) throw new Exception(); 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")) continue; - if (!File.Exists(filePath.Name)) + if (!File.Exists(filePath.FullName)) continue; checkFile = filePath.FullName[..^4]; if (File.Exists(checkFile)) @@ -470,7 +479,7 @@ internal abstract class MapLogic return results; } - private static void ParallelFor(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, Dictionary> skipCollection, List locationContainers, MappedFile mappedFile) + private static void ParallelFor(Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, ReadOnlyDictionary> skipCollection, List locationContainers, MappedFile mappedFile) { int? id; string checkFile; @@ -502,7 +511,7 @@ internal abstract class MapLogic } if (wholePercentages is null) 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(); foreach (string fileMatch in fileMatches) @@ -734,11 +743,11 @@ internal abstract class MapLogic } } - internal static ReadOnlyDictionary>> GetIdThenWholePercentagesToPersonContainers(Configuration configuration, ReadOnlyDictionary personKeyFormattedToPersonContainer, ReadOnlyCollection personKeyFormattedIdThenWholePercentagesCollection) + internal static ReadOnlyDictionary>> GetIdThenWholePercentagesToPersonContainers(Configuration configuration, Dictionary> skipCollection, ReadOnlyDictionary personKeyFormattedToPersonContainer, ReadOnlyCollection personKeyFormattedIdThenWholePercentagesCollection) { ReadOnlyDictionary>> results; Dictionary>> idThenWholePercentagesToPersonContainerCollection; - idThenWholePercentagesToPersonContainerCollection = GetAll(configuration, personKeyFormattedToPersonContainer, personKeyFormattedIdThenWholePercentagesCollection); + idThenWholePercentagesToPersonContainerCollection = GetAll(configuration, skipCollection, personKeyFormattedToPersonContainer, personKeyFormattedIdThenWholePercentagesCollection); results = GetReadOnly(idThenWholePercentagesToPersonContainerCollection); return results; } @@ -766,7 +775,7 @@ internal abstract class MapLogic wholePercentagesCollection = idToWholePercentagesCollection[record.MappedFaceFilePath.Id.Value]; wholePercentagesCollection.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); } @@ -890,7 +899,7 @@ internal abstract class MapLogic } } - internal static List GetLocationContainers(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, long ticks, ReadOnlyCollection personContainers, Dictionary> skipCollection, List records) + internal static List GetLocationContainers(int maxDegreeOfParallelism, Shared.Models.Properties.IPropertyConfiguration propertyConfiguration, Configuration configuration, long ticks, ReadOnlyCollection personContainers, ReadOnlyDictionary> skipCollection, List records) { List results = []; List mappedFiles = GetMappedFiles(propertyConfiguration, configuration, personContainers, records); diff --git a/Map/Models/Stateless/RelationLogic.cs b/Map/Models/Stateless/RelationLogic.cs index 216282b..25ad46f 100644 --- a/Map/Models/Stateless/RelationLogic.cs +++ b/Map/Models/Stateless/RelationLogic.cs @@ -84,7 +84,7 @@ internal abstract class RelationLogic return new(results); } - private static ReadOnlyDictionary MoveFiles(Configuration configuration, string key, bool isCounterPersonYear, string? displayDirectoryName, ReadOnlyCollection relationContainers, List linked1, List linked2, List linked3, List linked4, List linked5, List linked6, List linked7, List linked8, List linked9) + private static ReadOnlyDictionary MoveFiles(Configuration configuration, string key, bool isCounterPersonYear, string? displayDirectoryName, ReadOnlyCollection relationContainers, List> linked) { Dictionary results = []; string value; @@ -105,23 +105,55 @@ internal abstract class RelationLogic maybeTicksDirectoryName = Path.GetFileName(personKeyFormattedDirectory); if (string.IsNullOrEmpty(personNameDirectory) || string.IsNullOrEmpty(yearDirectory) || string.IsNullOrEmpty(personKeyFormattedDirectory) || string.IsNullOrEmpty(personNameDirectoryName)) 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"; - else if (linked8.Contains(fileHolder.FullName)) + else if (linked[7].Contains(fileHolder.FullName)) value = "III"; - else if (linked7.Contains(fileHolder.FullName)) + else if (linked[6].Contains(fileHolder.FullName)) value = "HHH"; - else if (linked6.Contains(fileHolder.FullName)) + else if (linked[5].Contains(fileHolder.FullName)) value = "GGG"; - else if (linked5.Contains(fileHolder.FullName)) + else if (linked[4].Contains(fileHolder.FullName)) value = "FFF"; - else if (linked4.Contains(fileHolder.FullName)) + else if (linked[3].Contains(fileHolder.FullName)) value = "EEE"; - else if (linked3.Contains(fileHolder.FullName)) + else if (linked[2].Contains(fileHolder.FullName)) value = "DDD"; - else if (linked2.Contains(fileHolder.FullName)) + else if (linked[1].Contains(fileHolder.FullName)) value = "CCC"; - else if (linked1.Contains(fileHolder.FullName)) + else if (linked[0].Contains(fileHolder.FullName)) value = "BBB"; else value = "AAA"; @@ -231,67 +263,24 @@ internal abstract class RelationLogic private static ReadOnlyDictionary GetMoveFiles(Configuration configuration, string key, int take, bool isCounterPersonYear, string? displayDirectoryName, ReadOnlyCollection relationContainers) { ReadOnlyDictionary results; - List linked1 = []; - List linked2 = []; - List linked3 = []; - List linked4 = []; - List linked5 = []; - List linked6 = []; - List linked7 = []; - List linked8 = []; - List linked9 = []; + List> linked = []; + for (int i = 0; i < 25; i++) + linked.Add([]); foreach ((FileHolder fileHolder, ReadOnlyCollection relations) in relationContainers) { foreach (Relation relation in relations.Take(take)) { - if (!linked1.Contains(relation.File)) + for (int i = 0; i < 25; i++) { - linked1.Add(relation.File); - continue; - } - if (!linked2.Contains(relation.File)) - { - 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; + if (!linked[i].Contains(relation.File)) + { + linked[i].Add(relation.File); + break; + } } } } - 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; } diff --git a/Metadata-Query/MetadataQuery.cs b/Metadata-Query/MetadataQuery.cs index 4553338..0d1c5c4 100644 --- a/Metadata-Query/MetadataQuery.cs +++ b/Metadata-Query/MetadataQuery.cs @@ -60,8 +60,8 @@ public class MetadataQuery private List<(string FileName, string TagGroup, string TagIdName, string Value)> GetCollection(long ticks) { string json; - string model; - string maker; + string? model; + string? maker; string message; FileInfo fileInfo; ProgressBar progressBar; diff --git a/Metadata/Models/Stateless/Base.cs b/Metadata/Models/Stateless/Base.cs index 8c56003..97ad98c 100644 --- a/Metadata/Models/Stateless/Base.cs +++ b/Metadata/Models/Stateless/Base.cs @@ -5,7 +5,7 @@ namespace View_by_Distance.Metadata.Models.Stateless.Methods; internal static class Base { - internal static string GetMaker(ExifDirectoryBase[]? exifBaseDirectories) + internal static string? GetMaker(ExifDirectoryBase[]? exifBaseDirectories) { string? result = null; if (exifBaseDirectories is not null) @@ -23,12 +23,10 @@ internal static class Base } } } - if (string.IsNullOrEmpty(result)) - result = "Unknown"; return result; } - internal static string GetModel(ExifDirectoryBase[]? exifBaseDirectories) + internal static string? GetModel(ExifDirectoryBase[]? exifBaseDirectories) { string? result = null; if (exifBaseDirectories is not null) @@ -46,8 +44,6 @@ internal static class Base } } } - if (string.IsNullOrEmpty(result)) - result = "Unknown"; return result; } diff --git a/Metadata/Models/Stateless/Methods/IMetadata.cs b/Metadata/Models/Stateless/Methods/IMetadata.cs index 8029fde..81926dc 100644 --- a/Metadata/Models/Stateless/Methods/IMetadata.cs +++ b/Metadata/Models/Stateless/Methods/IMetadata.cs @@ -19,14 +19,14 @@ public interface IMetadata static ExifDirectory GetExifDirectory(FilePath filePath) => Exif.GetExifDirectory(filePath); - string TestStatic_GetMaker(ExifDirectory? exifDirectory) => + string? TestStatic_GetMaker(ExifDirectory? exifDirectory) => GetMaker(exifDirectory); - static string GetMaker(ExifDirectory? exifDirectory) => + static string? GetMaker(ExifDirectory? exifDirectory) => Base.GetMaker(exifDirectory?.ExifBaseDirectories); - string TestStatic_GetModel(ExifDirectory? exifDirectory) => + string? TestStatic_GetModel(ExifDirectory? exifDirectory) => GetModel(exifDirectory); - static string GetModel(ExifDirectory? exifDirectory) => + static string? GetModel(ExifDirectory? exifDirectory) => Base.GetModel(exifDirectory?.ExifBaseDirectories); string? TestStatic_GetOutputResolution(ExifDirectory? exifDirectory) => diff --git a/Rename/Rename.cs b/Rename/Rename.cs index 747407f..c2e9ae0 100644 --- a/Rename/Rename.cs +++ b/Rename/Rename.cs @@ -402,7 +402,7 @@ public class Rename { if (record.Id is null) 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; checkFile = Path.Combine(seasonDirectory, $"{paddedId}{checkFileExtension}"); if (checkFile == fileHolder.FullName) diff --git a/Shared/Models/MappingFromFilterPre.cs b/Shared/Models/MappingFromFilterPre.cs index b6d4f00..e6782c5 100644 --- a/Shared/Models/MappingFromFilterPre.cs +++ b/Shared/Models/MappingFromFilterPre.cs @@ -14,6 +14,9 @@ public record MappingFromFilterPre(bool? InSkipCollection, return result; } + internal static void Constructor() => + _ = new MappingFromFilterPre(null, null, null); + } [JsonSourceGenerationOptions(WriteIndented = true)] diff --git a/Shared/Models/Stateless/Methods/Container.cs b/Shared/Models/Stateless/Methods/Container.cs index c24ea22..fcfdff6 100644 --- a/Shared/Models/Stateless/Methods/Container.cs +++ b/Shared/Models/Stateless/Methods/Container.cs @@ -194,11 +194,11 @@ internal abstract class Container return (count, results); } - internal static List GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers) + internal static List GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection readOnlyContainers) { List results = []; Models.Item[] filteredItems; - foreach (Models.Container container in containers) + foreach (Models.Container container in readOnlyContainers) { if (container.Items.Count == 0) continue; diff --git a/Shared/Models/Stateless/Methods/IContainer.cs b/Shared/Models/Stateless/Methods/IContainer.cs index ad578fd..2f8a42d 100644 --- a/Shared/Models/Stateless/Methods/IContainer.cs +++ b/Shared/Models/Stateless/Methods/IContainer.cs @@ -25,10 +25,10 @@ public interface IContainer static (int, Models.Container[]) GetContainers(Properties.IPropertyConfiguration propertyConfiguration, string aPropertySingletonDirectory, string filesCollectionDirectory, ReadOnlyCollection filesCollection) => Container.GetContainers(propertyConfiguration, aPropertySingletonDirectory, filesCollectionDirectory, filesCollection); - List TestStatic_GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers) => - GetFilteredDistinctIds(propertyConfiguration, containers); - static List GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, Models.Container[] containers) => - Container.GetFilteredDistinctIds(propertyConfiguration, containers); + List TestStatic_GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection readOnlyContainers) => + GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers); + static List GetFilteredDistinctIds(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection readOnlyContainers) => + Container.GetFilteredDistinctIds(propertyConfiguration, readOnlyContainers); ReadOnlyCollection TestStatic_GetItems(Properties.IPropertyConfiguration propertyConfiguration, ReadOnlyCollection containers, bool distinctItems, bool filterItems) => GetItems(propertyConfiguration, containers, distinctItems, filterItems); diff --git a/Shared/Models/Stateless/Methods/IId.cs b/Shared/Models/Stateless/Methods/IId.cs index ab79276..407d037 100644 --- a/Shared/Models/Stateless/Methods/IId.cs +++ b/Shared/Models/Stateless/Methods/IId.cs @@ -13,10 +13,10 @@ public interface IId static int GetId(Properties.IPropertyConfiguration propertyConfiguration, string intelligentId) => Id.GetId(propertyConfiguration, intelligentId); - string TestStatic_GetPaddedId(Properties.IPropertyConfiguration propertyConfiguration, int index, int id) => - GetPaddedId(propertyConfiguration, index, id); - static string GetPaddedId(Properties.IPropertyConfiguration propertyConfiguration, int index, int id) => - Id.GetPaddedId(propertyConfiguration, index, id); + string TestStatic_GetPaddedId(Properties.IPropertyConfiguration propertyConfiguration, int id, int? index) => + GetPaddedId(propertyConfiguration, id, index); + static string GetPaddedId(Properties.IPropertyConfiguration propertyConfiguration, int id, int? index) => + Id.GetPaddedId(propertyConfiguration, id, index); bool TestStatic_IsIgnore(FilePath filePath) => IsIgnore(filePath); diff --git a/Shared/Models/Stateless/Methods/Id.cs b/Shared/Models/Stateless/Methods/Id.cs index ea69b18..39cbdee 100644 --- a/Shared/Models/Stateless/Methods/Id.cs +++ b/Shared/Models/Stateless/Methods/Id.cs @@ -62,14 +62,19 @@ internal abstract class Id 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 intelligentId = GetIntelligentId(propertyConfiguration, id, ignore: false); - int check = GetId(propertyConfiguration, intelligentId); - if (check != id) - throw new NotSupportedException(); - result = $"{propertyConfiguration.Offset + index}{intelligentId}"; + if (propertyConfiguration.Offset < 0) + result = Guid.NewGuid().ToString(); + else + { + 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; } diff --git a/Shared/Models/Stateless/Methods/XDirectory.cs b/Shared/Models/Stateless/Methods/XDirectory.cs index b36e727..553d1de 100644 --- a/Shared/Models/Stateless/Methods/XDirectory.cs +++ b/Shared/Models/Stateless/Methods/XDirectory.cs @@ -324,7 +324,7 @@ internal abstract partial class XDirectory } 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}"); if (!File.Exists(paddedIdFile)) {