AA.Compare Project to Match not runToDoCollectionFirst

Removed Layered AppSettings with Nested Objects at First Level
This commit is contained in:
2024-12-28 19:34:09 -07:00
parent 3ff8153393
commit 0215e838e7
110 changed files with 6331 additions and 1275 deletions

50
Compare/AA.Compare.csproj Normal file
View File

@ -0,0 +1,50 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net9.0</TargetFramework>
<UserSecretsId>770b6ae3-266e-4d5f-970a-173709b064de</UserSecretsId>
</PropertyGroup>
<PropertyGroup>
<PackageId>Phares.View.by.Distance.Compare</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>9.0.100.0</Version>
<Authors>Mike Phares</Authors>
<Company>Phares</Company>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<PropertyGroup>
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
<IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX>
<IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
</PropertyGroup>
<PropertyGroup Condition="'$(IsWindows)'=='true'">
<DefineConstants>Windows</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsOSX)'=='true'">
<DefineConstants>OSX</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsLinux)'=='true'">
<DefineConstants>Linux</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'browser-wasm'">
<SupportedPlatform Include="browser" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="runtime.win-x64.Microsoft.DotNet.ILCompiler" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.0" />
<PackageReference Include="ShellProgressBar" Version="5.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Face\AA.Face.csproj" />
<ProjectReference Include="..\Distance\AA.Distance.csproj" />
<ProjectReference Include="..\Metadata\AA.Metadata.csproj" />
<ProjectReference Include="..\People\AA.People.csproj" />
<ProjectReference Include="..\Shared\AA.Shared.csproj" />
</ItemGroup>
</Project>

168
Compare/Compare.cs Normal file
View File

@ -0,0 +1,168 @@
using Microsoft.Extensions.Logging;
using ShellProgressBar;
using System.Collections.ObjectModel;
using View_by_Distance.Compare.Models;
using View_by_Distance.Distance.Models.Stateless.Methods;
using View_by_Distance.Face.Models.Stateless.Methods;
using View_by_Distance.Metadata.Models;
using View_by_Distance.People.Models.Stateless.Methods;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Stateless.Methods;
namespace View_by_Distance.Compare;
public partial class Compare : ICompare, IDisposable
{
private ProgressBar? _ProgressBar;
private readonly ProgressBarOptions _ProgressBarOptions;
public Compare(List<string> args, ILogger<Program>? logger, AppSettings appSettings, bool isSilent, IConsole console)
{
if (isSilent)
{ }
if (args is null)
throw new NullReferenceException(nameof(args));
if (console is null)
throw new NullReferenceException(nameof(console));
ICompare compare = this;
long ticks = DateTime.Now.Ticks;
_ProgressBarOptions = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
CompareWork(logger, appSettings, compare, ticks);
}
void ICompare.Tick() =>
_ProgressBar?.Tick();
void ICompare.ConstructProgressBar(int maxTicks, string message)
{
_ProgressBar?.Dispose();
_ProgressBar = new(maxTicks, message, _ProgressBarOptions);
}
void IDisposable.Dispose()
{
_ProgressBar?.Dispose();
GC.SuppressFinalize(this);
}
private static bool GetRunToDoCollectionFirst(AppSettings appSettings, long ticks)
{
bool result = appSettings.DistanceSettings.SaveSortingWithoutPerson;
if (!result)
result = !IId.IsOffsetDeterministicHashCode(appSettings.MetadataSettings);
if (!result)
{
string[] directories;
directories = Directory.GetDirectories(appSettings.ResultSettings.RootDirectory, "*", SearchOption.TopDirectoryOnly);
if (directories.Length == 0)
result = true;
else
{
string seasonDirectory;
DirectoryInfo directoryInfo;
DateTime dateTime = new(ticks);
string rootDirectory = appSettings.ResultSettings.RootDirectory;
(int season, string seasonName) = IDate.GetSeason(dateTime.DayOfYear);
string eDistanceContentDirectory = IResult.GetResultsDateGroupDirectory(appSettings.ResultSettings, nameof(E_Distance), appSettings.ResultSettings.ResultContent);
FileSystemInfo fileSystemInfo = new DirectoryInfo(eDistanceContentDirectory);
string[] checkDirectories =
[
Path.Combine(rootDirectory, "Ancestry"),
Path.Combine(rootDirectory, "Facebook"),
Path.Combine(rootDirectory, "LinkedIn")
];
foreach (string checkDirectory in checkDirectories)
{
if (checkDirectory == rootDirectory)
seasonDirectory = Path.Combine(checkDirectory, $"{dateTime.Year}.{season} {seasonName}");
else
seasonDirectory = Path.Combine(checkDirectory, $"{dateTime.Year}.{season} {seasonName} {Path.GetFileName(checkDirectory)}");
if (!Directory.Exists(seasonDirectory))
_ = Directory.CreateDirectory(seasonDirectory);
if (result)
continue;
directories = Directory.GetDirectories(checkDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string directory in directories)
{
directoryInfo = new(directory);
if (directoryInfo.LastWriteTime > fileSystemInfo.LastWriteTime)
{
result = true;
break;
}
}
}
}
}
if (result)
result = true;
if (!result)
result = false;
return result;
}
private static ReadOnlyCollections GetReadOnlyCollections(AppSettings appSettings)
{
ReadOnlyCollections result;
ReadOnlyCollection<PersonContainer> personContainers = IPeople.GetPersonContainers(appSettings.ResultSettings, appSettings.MetadataSettings, appSettings.PeopleSettings, appSettings.CompareSettings);
ReadOnlyCollection<long> personKeys = IPeople.GetPersonKeys(personContainers);
result = IPeople.GetReadOnlyCollections(appSettings.ResultSettings, appSettings.PeopleSettings, appSettings.DistanceSettings, appSettings.CompareSettings, personContainers, personKeys);
return result;
}
private static ReadOnlyCollection<ExifDirectory> GetMappedExifDirectoryWithEncoding(AppSettings appSettings, ICompare compare, long ticks, ReadOnlyCollections readOnlyCollections)
{
ReadOnlyCollection<ExifDirectory> results;
ReadOnlyCollection<ExifDirectory> exifDirectories = IDistance.GetMapped(appSettings.ResultSettings, appSettings.MetadataSettings, appSettings.PeopleSettings, appSettings.DistanceSettings, appSettings.CompareSettings, compare, ticks, readOnlyCollections);
if (exifDirectories.Count == 0 && !appSettings.DistanceSettings.SaveSortingWithoutPerson)
throw new NotSupportedException($"Switch {nameof(appSettings.DistanceSettings.SaveSortingWithoutPerson)}!");
results = IDistance.GetMappedExifDirectoryWithEncoding(compare, ticks, exifDirectories);
if (results.Count == 0 && !appSettings.DistanceSettings.SaveSortingWithoutPerson)
throw new NotSupportedException($"Switch {nameof(appSettings.DistanceSettings.SaveSortingWithoutPerson)}!");
return results;
}
private void CompareWork(ILogger<Program>? logger, AppSettings appSettings, ICompare compare, long ticks)
{
const int updated = 0;
DistanceLimits? distanceLimits;
logger?.LogInformation("{Ticks}", ticks);
ReadOnlyCollection<LocationContainer> matrix;
ReadOnlyCollection<SaveContainer> saveContainers;
ReadOnlyCollection<ExifDirectory> exifDirectories;
ReadOnlyCollection<LocationContainer> preFiltered;
ReadOnlyCollection<LocationContainer> postFiltered;
ReadOnlyDictionary<string, LocationContainer> onlyOne;
bool runToDoCollectionFirst = GetRunToDoCollectionFirst(appSettings, ticks);
ReadOnlyCollections readOnlyCollections = GetReadOnlyCollections(appSettings);
ReadOnlyCollection<ExifDirectory> mappedExifDirectoryWithEncoding = GetMappedExifDirectoryWithEncoding(appSettings, compare, ticks, readOnlyCollections);
ReadOnlyDictionary<int, ReadOnlyDictionary<int, FilePath>> keyValuePairs = IDistance.Extract(appSettings.CompareSettings, mappedExifDirectoryWithEncoding);
foreach (string outputResolution in appSettings.CompareSettings.OutputResolutions)
{
if (runToDoCollectionFirst || outputResolution.Any(char.IsNumber))
continue;
_ProgressBar?.Dispose();
logger?.LogInformation("{outputResolution}", outputResolution);
exifDirectories = IFace.GetExifDirectories(appSettings.ResultSettings, appSettings.MetadataSettings, appSettings.DistanceSettings, appSettings.CompareSettings, compare, ticks, outputResolution);
preFiltered = IDistance.GetPreFilterLocationContainer(appSettings.DistanceSettings, appSettings.CompareSettings, compare, ticks, readOnlyCollections, keyValuePairs, exifDirectories);
if (preFiltered.Count == 0)
continue;
distanceLimits = new(appSettings.DistanceSettings);
postFiltered = IDistance.GetPostFilterLocationContainer(preFiltered, distanceLimits);
if (postFiltered.Count == 0)
continue;
matrix = IDistance.GetMatrixLocationContainers(appSettings.DistanceSettings, appSettings.CompareSettings, compare, ticks, mappedExifDirectoryWithEncoding, distanceLimits, postFiltered);
if (matrix.Count == 0)
continue;
onlyOne = IDistance.GetOnlyOne(appSettings.DistanceSettings, matrix);
if (onlyOne.Count == 0)
continue;
saveContainers = IDistance.GetSaveContainers(appSettings.ResultSettings, appSettings.DistanceSettings, appSettings.CompareSettings, compare, ticks, outputResolution, onlyOne);
if (saveContainers.Count == 0)
continue;
IDistance.SaveContainers(appSettings.DistanceSettings, appSettings.CompareSettings, compare, ticks, updated, saveContainers);
}
}
}

View File

@ -0,0 +1,78 @@
using Microsoft.Extensions.Configuration;
using System.Text.Json;
using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models;
namespace View_by_Distance.Compare.Models;
public record AppSettings(ResultSettings ResultSettings,
MetadataSettings MetadataSettings,
PeopleSettings PeopleSettings,
DistanceSettings DistanceSettings,
CompareSettings CompareSettings)
{
public override string ToString()
{
string result = JsonSerializer.Serialize(this, AppSettingsSourceGenerationContext.Default.AppSettings);
return result;
}
private static void Verify(AppSettings appSettings)
{
if (appSettings.DistanceSettings.RangeDaysDeltaTolerance.Length != 3)
throw new NullReferenceException(nameof(appSettings.DistanceSettings.RangeDaysDeltaTolerance));
if (appSettings.DistanceSettings.RangeDistanceTolerance.Length != 3)
throw new NullReferenceException(nameof(appSettings.DistanceSettings.RangeDistanceTolerance));
if (appSettings.DistanceSettings.RangeFaceAreaTolerance.Length != 3)
throw new NullReferenceException(nameof(appSettings.DistanceSettings.RangeFaceAreaTolerance));
if (appSettings.DistanceSettings.RangeFaceConfidence.Length != 3)
throw new NullReferenceException(nameof(appSettings.DistanceSettings.RangeFaceConfidence));
_ = DateTime.Now.AddDays(-appSettings.DistanceSettings.RangeDaysDeltaTolerance[1]);
if (appSettings.DistanceSettings.SaveSortingWithoutPerson && appSettings.PeopleSettings.JLinks.Length > 0)
throw new Exception("Settings has SaveSortingWithoutPerson and JLinks!");
if (appSettings.DistanceSettings.SaveSortingWithoutPerson && !string.IsNullOrEmpty(appSettings.DistanceSettings.FocusModel))
throw new Exception("Settings has SaveSortingWithoutPerson and FocusModel!");
if (appSettings.DistanceSettings.SaveSortingWithoutPerson && !string.IsNullOrEmpty(appSettings.DistanceSettings.FocusDirectory))
throw new Exception("Settings has SaveSortingWithoutPerson and FocusDirectory!");
if (appSettings.CompareSettings.MaxDegreeOfParallelism > Environment.ProcessorCount)
throw new Exception("MaxDegreeOfParallelism must be =< Environment.ProcessorCount!");
if (!string.IsNullOrEmpty(appSettings.DistanceSettings.FocusDirectory) && appSettings.DistanceSettings.FocusDirectory.Length != 2)
throw new NotSupportedException($"{nameof(appSettings.DistanceSettings.FocusDirectory)} currently only works with output directory! Example 00.");
}
public static AppSettings Get(IConfigurationRoot configurationRoot)
{
AppSettings result;
#pragma warning disable IL3050, IL2026
ResultSettings? resultSettings = configurationRoot.GetSection(nameof(ResultSettings)).Get<ResultSettings>();
MetadataSettings? metadataSettings = configurationRoot.GetSection(nameof(MetadataSettings)).Get<MetadataSettings>();
PeopleSettings? peopleSettings = configurationRoot.GetSection(nameof(PeopleSettings)).Get<PeopleSettings>();
DistanceSettings? distanceSettings = configurationRoot.GetSection(nameof(DistanceSettings)).Get<DistanceSettings>();
CompareSettings? compareSettings = configurationRoot.GetSection(nameof(CompareSettings)).Get<CompareSettings>();
#pragma warning restore IL3050, IL2026
if (resultSettings is null || metadataSettings is null || peopleSettings is null || distanceSettings is null || compareSettings?.Company is null)
{
List<string> paths = [];
foreach (IConfigurationProvider configurationProvider in configurationRoot.Providers)
{
if (configurationProvider is not Microsoft.Extensions.Configuration.Json.JsonConfigurationProvider jsonConfigurationProvider)
continue;
if (jsonConfigurationProvider.Source.FileProvider is not Microsoft.Extensions.FileProviders.PhysicalFileProvider physicalFileProvider)
continue;
paths.Add(physicalFileProvider.Root);
}
throw new NotSupportedException($"Not found!{Environment.NewLine}{string.Join(Environment.NewLine, paths.Distinct())}");
}
result = new(resultSettings, metadataSettings, peopleSettings, distanceSettings, compareSettings);
Verify(result);
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(AppSettings))]
internal partial class AppSettingsSourceGenerationContext : JsonSerializerContext
{
}

View File

@ -0,0 +1,30 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Compare.Models;
public record CompareSettings(string Company,
string FacesFileNameExtension,
string FacesHiddenFileNameExtension,
string FacesPartsFileNameExtension,
string[] IgnoreExtensions,
int MaxDegreeOfParallelism,
string[] OutputResolutions,
string[] ValidImageFormatExtensions,
string[] ValidVideoFormatExtensions) : Shared.Models.Properties.ICompareSettings
{
public override string ToString()
{
string result = JsonSerializer.Serialize(this, CompareSettingsSourceGenerationContext.Default.CompareSettings);
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(CompareSettings))]
internal partial class CompareSettingsSourceGenerationContext : JsonSerializerContext
{
}

View File

@ -0,0 +1,32 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Compare.Models;
internal sealed record Identifier(string[] DirectoryNames,
bool? HasDateTimeOriginal,
int Id,
long Length,
string PaddedId,
long Ticks)
{
public override string ToString()
{
string result = JsonSerializer.Serialize(this, IdentifierSourceGenerationContext.Default.Identifier);
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Identifier))]
internal partial class IdentifierSourceGenerationContext : JsonSerializerContext
{
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Identifier[]))]
internal partial class IdentifierCollectionSourceGenerationContext : JsonSerializerContext
{
}

53
Compare/Program.cs Normal file
View File

@ -0,0 +1,53 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using View_by_Distance.Compare.Models;
namespace View_by_Distance.Compare;
public class Program
{
public static void Secondary(ILogger<Program> logger, List<string> args)
{
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
.AddEnvironmentVariables()
.AddUserSecrets<Program>();
IConfigurationRoot configurationRoot = configurationBuilder.Build();
AppSettings appSettings = AppSettings.Get(configurationRoot);
int silentIndex = args.IndexOf("s");
if (silentIndex > -1)
args.RemoveAt(silentIndex);
try
{
if (args is null)
throw new Exception("args is null!");
Shared.Models.Console console = new();
_ = new Compare(args, logger, appSettings, silentIndex > -1, console);
}
catch (Exception ex)
{
logger?.LogError(ex, "Error!");
}
if (silentIndex > -1)
logger?.LogInformation("Done. Bye");
else
{
logger?.LogInformation("Done. Press 'Enter' to end");
_ = Console.ReadLine();
}
}
public static void Main(string[] args)
{
#pragma warning disable IL3050
ILogger<Program>? logger = Host.CreateDefaultBuilder(args).Build().Services.GetRequiredService<ILogger<Program>>();
#pragma warning restore IL3050
if (args is not null)
Secondary(logger, args.ToList());
else
Secondary(logger, []);
}
}