This commit is contained in:
2022-05-08 12:28:50 -07:00
commit 4a3e24236f
313 changed files with 22395 additions and 0 deletions

1
Date-Group/.vscode/format-report.json vendored Normal file
View File

@ -0,0 +1 @@
[]

30
Date-Group/.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,30 @@
{
"version": "0.2.0",
"configurations": [
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/bin/Debug/net6.0/win-x64/Date-Group.dll",
"args": [],
"env": {
"ASPNETCORE_ENVIRONMENT": "Development",
},
"cwd": "${workspaceFolder}",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "externalTerminal",
"stopAtEntry": false
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processName": "Date-Group"
}
]
}

11
Date-Group/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,11 @@
{
"cSpell.words": [
"Barrick",
"Beichler",
"Bohdi",
"Dlib",
"Phares",
"Serilog",
"Vericruz"
]
}

42
Date-Group/.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,42 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/Date-Group.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "publish",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/Date-Group.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"${workspaceFolder}/Date-Group.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
}
]
}

View File

@ -0,0 +1,63 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>10.0</LangVersion>
<Nullable>enable</Nullable>
<OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<PackageId>Phares.View.by.Distance.Date.Group</PackageId>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>5.0.402.104</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="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MetadataExtractor" Version="2.7.1" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.3.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.1" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="ShellProgressBar" Version="5.1.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="6.0.0" />
<PackageReference Include="System.Text.Json" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\View-by-Distance.Shared.csproj" />
<ProjectReference Include="..\Property\Property.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="appsettings.Development.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

426
Date-Group/DateGroup.cs Normal file
View File

@ -0,0 +1,426 @@
using Microsoft.Extensions.Configuration;
using Phares.Shared;
using System.Globalization;
using System.Text;
using View_by_Distance.Date.Group.Models;
using View_by_Distance.Property.Models;
using View_by_Distance.Shared.Models.Methods;
namespace View_by_Distance.Date.Group;
public class DateGroup
{
private readonly Serilog.ILogger? _Log;
private readonly AppSettings _AppSettings;
private readonly List<string> _Exceptions;
private readonly IsEnvironment _IsEnvironment;
private readonly Models.Configuration _Configuration;
private readonly List<KeyValuePair<string, string>> _FileKeyValuePairs;
private readonly Dictionary<string, List<Tuple<string, A_Property>>> _FilePropertiesKeyValuePairs;
public DateGroup(List<string> args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console)
{
if (isSilent)
{ }
if (args is null)
{ }
if (console is null)
{ }
_AppSettings = appSettings;
if (appSettings.MaxDegreeOfParallelism is null)
throw new Exception($"{nameof(appSettings.MaxDegreeOfParallelism)} is null!");
_IsEnvironment = isEnvironment;
_Exceptions = new List<string>();
_Log = Serilog.Log.ForContext<DateGroup>();
_FileKeyValuePairs = new List<KeyValuePair<string, string>>();
_FilePropertiesKeyValuePairs = new Dictionary<string, List<Tuple<string, A_Property>>>();
Property.Models.Configuration propertyConfiguration = Property.Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory);
Property.Models.Configuration.Verify(propertyConfiguration);
Models.Configuration configuration = Models.Stateless.Configuration.Get(isEnvironment, configurationRoot, workingDirectory, propertyConfiguration);
Verify(configuration);
_Configuration = configuration;
if (configuration.ByHash is null)
throw new Exception($"{nameof(configuration.ByHash)} is null!");
if (propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass is null)
throw new Exception($"{nameof(propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass)} is null!");
if (propertyConfiguration.PopulatePropertyId is null)
throw new Exception($"{nameof(propertyConfiguration.PopulatePropertyId)} is null!");
if (!_IsEnvironment.Development)
throw new Exception("This program only allows development environments!");
string searchPattern = "*";
long ticks = DateTime.Now.Ticks;
List<string> topDirectories = new();
PropertyLogic propertyLogic = GetPropertyLogic();
string[] dbFiles = Directory.GetFiles(propertyConfiguration.RootDirectory, "*.db", SearchOption.AllDirectories);
foreach (string dbFile in dbFiles)
File.Delete(dbFile);
for (int i = 1; i < 10; i++)
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory);
List<(int g, string sourceDirectory, string[] sourceDirectoryFiles, int r)> groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false);
if (appSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection));
List<Property.Models.Group> groupResultsCollection = new();
if (!propertyConfiguration.PopulatePropertyId.Value || !configuration.ByHash.Value)
groupResultsCollection = propertyLogic.GetParallelWork(propertyConfiguration, topDirectories, groupCollection, firstPass: true, filterOnFirstPass: true);
else
{
_Exceptions.AddRange(propertyLogic.DoWork(propertyConfiguration, topDirectories, groupCollection, firstPass: true));
string message = $"There were {_Exceptions.Count} exception(s) thrown! {Environment.NewLine}{string.Join(Environment.NewLine, _Exceptions)}";
_Log.Information(message);
if (_Exceptions.Count != 0)
throw new Exception(message);
if (appSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(PropertyLogic.DoWork));
topDirectories.Clear();
groupCollection = Property.Models.Stateless.A_Property.GetGroupCollection(propertyConfiguration.RootDirectory, searchPattern, topDirectories, propertyConfiguration.MaxImagesInDirectoryForTopLevelFirstPass.Value, reverse: false);
if (appSettings.MaxDegreeOfParallelism.Value < 2)
ticks = LogDelta(ticks, nameof(Property.Models.Stateless.A_Property.GetGroupCollection));
groupResultsCollection = propertyLogic.GetParallelWork(propertyConfiguration, topDirectories, groupCollection, firstPass: false, filterOnFirstPass: true);
}
MoveFiles(topDirectories, groupResultsCollection);
}
private static void Verify(Models.Configuration configuration)
{
if (configuration.ByDay is null)
throw new Exception($"{nameof(configuration.ByDay)} is null!");
if (configuration.ByHash is null)
throw new Exception($"{nameof(configuration.ByHash)} is null!");
if (configuration.BySeason is null)
throw new Exception($"{nameof(configuration.BySeason)} is null!");
if (configuration.ByWeek is null)
throw new Exception($"{nameof(configuration.ByWeek)} is null!");
if (!configuration.ByDay.Value && !configuration.ByWeek.Value && !configuration.BySeason.Value && !configuration.ByHash.Value)
throw new Exception("Change configuration!");
if (configuration.KeepFullPath is null)
throw new Exception($"{nameof(configuration.KeepFullPath)} is null!");
if (configuration?.PropertyConfiguration?.PopulatePropertyId is null)
throw new Exception($"{nameof(configuration.PropertyConfiguration.PopulatePropertyId)} must be set!");
if (configuration.PropertyConfiguration.PopulatePropertyId.Value && !configuration.ByHash.Value)
throw new Exception("Change configuration!");
if (!configuration.PropertyConfiguration.PopulatePropertyId.Value && configuration.ByHash.Value)
throw new Exception("Change configuration!");
if (configuration.ByDay.Value && configuration.ByWeek.Value && configuration.BySeason.Value && configuration.ByHash.Value)
throw new Exception("Change configuration!");
}
private static bool WriteAllText(string path, string contents, bool compareBeforeWrite)
{
bool result;
string text;
if (!compareBeforeWrite)
result = true;
else
{
if (!File.Exists(path))
text = string.Empty;
else
text = File.ReadAllText(path);
result = text != contents;
}
if (result)
{
if (path.Contains("()"))
File.WriteAllText(path, contents);
else if (path.Contains("{}") && !path.EndsWith(".json"))
File.WriteAllText(path, contents);
else if (path.Contains("[]") && !path.EndsWith(".json"))
File.WriteAllText(path, contents);
else if (path.Contains("{}") && path.EndsWith(".json") && contents[0] == '{')
File.WriteAllText(path, contents);
else if (path.Contains("[]") && path.EndsWith(".json") && contents[0] == '[')
File.WriteAllText(path, contents);
else
File.WriteAllText(path, contents);
}
return result;
}
private long LogDelta(long ticks, string methodName)
{
long result;
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
double delta = new TimeSpan(DateTime.Now.Ticks - ticks).TotalMilliseconds;
_Log.Debug($"{methodName} took {Math.Floor(delta)} millisecond(s)");
result = DateTime.Now.Ticks;
return result;
}
private List<(string Source, string[] Destination)> GetMoveFileCollection(string destinationDirectory, string topDirectory, Property.Models.Group group)
{
List<(string Source, string[] Destination)> results = new();
if (_Configuration.ByDay is null)
throw new Exception($"{nameof(_Configuration.ByDay)} is null!");
if (_Configuration.ByHash is null)
throw new Exception($"{nameof(_Configuration.ByHash)} is null!");
if (_Configuration.BySeason is null)
throw new Exception($"{nameof(_Configuration.BySeason)} is null!");
if (_Configuration.ByWeek is null)
throw new Exception($"{nameof(_Configuration.ByWeek)} is null!");
if (_Configuration.KeepFullPath is null)
throw new Exception($"{nameof(_Configuration.KeepFullPath)} is null!");
char flag;
string day;
int season;
string year;
string month;
string? check;
string fileName;
string? pathRoot;
string seasonName;
string weekOfYear;
string? directory;
string seasonValue;
A_Property? property;
string directoryName;
bool? propertyWrongYear;
string topDirectoryName;
string[]? matches = null;
string[] directorySegments;
DateTime? minimumDateTime = null;
List<string> destinationCollection;
string filteredSourceDirectoryFile;
List<string> directoryNames = new();
List<string> topDirectorySegments = new();
StringBuilder destinationDirectoryName = new();
Calendar calendar = new CultureInfo("en-US").Calendar;
for (int z = 1; z < 3; z++)
{
if (z == 1)
{
check = Path.Combine(destinationDirectory, ".");
pathRoot = Path.GetPathRoot(destinationDirectory);
}
else if (z == 2)
{
check = Path.Combine(topDirectory, ".");
pathRoot = Path.GetPathRoot(topDirectory);
}
else
throw new Exception();
if (string.IsNullOrEmpty(pathRoot))
continue;
for (int i = 0; i < int.MaxValue; i++)
{
check = Path.GetDirectoryName(check);
if (string.IsNullOrEmpty(check) || check == pathRoot)
break;
directoryName = Path.GetFileName(check);
directorySegments = directoryName.Split(' ');
topDirectorySegments.AddRange(directorySegments);
(_, matches) = Property.Models.Stateless.A_Property.IsWrongYear(directorySegments, string.Empty);
if (matches.Any())
break;
}
if (matches is not null && matches.Any())
break;
}
if (matches is null)
matches = Array.Empty<string>();
for (int i = 0; i < group.FilteredSourceDirectoryFiles.Length; i++)
{
destinationCollection = new();
directoryNames.Clear();
_ = destinationDirectoryName.Clear();
property = group.PropertyCollection[i];
if (property is null)
continue;
filteredSourceDirectoryFile = group.FilteredSourceDirectoryFiles[i];
minimumDateTime = Property.Models.Stateless.A_Property.GetMinimumDateTime(property);
directory = Path.GetDirectoryName(filteredSourceDirectoryFile);
if (string.IsNullOrEmpty(directory))
continue;
day = minimumDateTime.Value.ToString("MM-dd");
month = minimumDateTime.Value.ToString("MMMM");
(propertyWrongYear, _) = property.IsWrongYear(filteredSourceDirectoryFile, minimumDateTime);
if (propertyWrongYear is null)
flag = '#';
else
{
if (propertyWrongYear.Value)
flag = '~';
else
{
if (property.DateTimeOriginal.HasValue && minimumDateTime.Value.DayOfYear != property.DateTimeOriginal.Value.DayOfYear && Math.Abs(new TimeSpan(minimumDateTime.Value.Ticks - property.DateTimeOriginal.Value.Ticks).TotalHours) > 8)
flag = '^';
else
flag = '=';
}
}
(season, seasonName) = Property.Models.Stateless.A_Property.GetSeason(minimumDateTime.Value.DayOfYear);
if ((from l in topDirectorySegments where l == "Christmas" select true).Any())
seasonValue = string.Empty;
else
seasonValue = $".{season}";
if (propertyWrongYear is null || !propertyWrongYear.Value)
year = $"{flag}{minimumDateTime.Value:yyyy}{seasonValue}";
else
{
if (matches[0][0] != '~')
year = $"{flag}{matches[0].Split('.')[0]}{seasonValue}";
else
year = $"{flag}{matches[0][1..].Split('.')[0]}{seasonValue}";
}
topDirectoryName = Path.GetFileName(topDirectory);
weekOfYear = calendar.GetWeekOfYear(minimumDateTime.Value, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00");
if (_Configuration.ByHash.Value)
directoryNames.Add($"{year} {seasonName}");
else if (_Configuration.BySeason.Value && topDirectoryName.Length == 1 && topDirectoryName[0] == '_')
directoryNames.Add($"{year} {seasonName}");
else
{
if (!_Configuration.KeepFullPath.Value)
{
_ = destinationDirectoryName.Append(topDirectoryName);
if (_Configuration.BySeason.Value)
directoryNames.AddRange(new string[] { $"{destinationDirectoryName} {year}", $"{year} {seasonName}" });
else if (_Configuration.ByDay.Value)
directoryNames.AddRange(new string[] { $"{destinationDirectoryName} {year}", $"{weekOfYear}) {year}-{day}" });
else if (_Configuration.ByWeek.Value)
directoryNames.AddRange(new string[] { $"{destinationDirectoryName} {year}", $"{weekOfYear}) {year} {month}" });
else
throw new Exception();
}
else
{
foreach (string sourceDirectoryNameSegment in topDirectorySegments)
{
if (matches.Contains(sourceDirectoryNameSegment))
_ = destinationDirectoryName.Append(year);
else
_ = destinationDirectoryName.Append(sourceDirectoryNameSegment);
}
if (_Configuration.BySeason.Value)
directoryNames.Add($"{year} {seasonName}");
else if (_Configuration.ByDay.Value)
directoryNames.Add($"{weekOfYear}) {year} {day}");
else if (_Configuration.ByWeek.Value)
directoryNames.Add($"{weekOfYear}) {month} {year}");
else
throw new Exception();
}
}
if (!_Configuration.ByHash.Value || property.Id is null)
fileName = Path.GetFileName(filteredSourceDirectoryFile);
else
fileName = $"{property.Id.Value}{Path.GetExtension(filteredSourceDirectoryFile).ToLower()}";
destinationCollection.Add(destinationDirectory);
destinationCollection.AddRange(directoryNames);
destinationCollection.Add(fileName);
results.Add(new(filteredSourceDirectoryFile, destinationCollection.ToArray()));
}
return results;
}
private PropertyLogic GetPropertyLogic()
{
PropertyLogic result;
string[] verifyToSeason = Array.Empty<string>();
if (_AppSettings.MaxDegreeOfParallelism is null)
throw new Exception($"{nameof(_AppSettings.MaxDegreeOfParallelism)} is null!");
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
result = new(_AppSettings.MaxDegreeOfParallelism.Value, _Configuration.PropertyConfiguration, verifyToSeason);
return result;
}
private List<(string Source, string[] Destination)> GetFileMoveCollectionAll(List<string> topDirectories, List<Property.Models.Group> groupCollection)
{
List<(string Source, string[] Destination)> results = new();
if (_Configuration.KeepFullPath is null)
throw new Exception($"{nameof(_Configuration.KeepFullPath)} is null!");
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
string? topDirectory;
string? checkDirectory;
string sourceDirectory;
string destinationDirectory;
string destinationRoot = Property.Models.Stateless.IResult.GetResultsGroupDirectory(_Configuration.PropertyConfiguration, "Z) Moved");
List<(string Source, string[] Destination)> fileMoveCollectionDirectory;
foreach (Property.Models.Group group in groupCollection)
{
sourceDirectory = group.SourceDirectory;
if (!_Configuration.KeepFullPath.Value)
destinationDirectory = destinationRoot;
else
destinationDirectory = string.Concat(destinationRoot, sourceDirectory[_Configuration.PropertyConfiguration.RootDirectory.Length..]);
checkDirectory = Path.GetFullPath(sourceDirectory);
for (int z = 0; z < int.MaxValue; z++)
{
if (checkDirectory == _Configuration.PropertyConfiguration.RootDirectory || topDirectories.Contains(checkDirectory))
break;
checkDirectory = Path.GetDirectoryName(checkDirectory);
if (string.IsNullOrEmpty(checkDirectory))
break;
}
if (string.IsNullOrEmpty(checkDirectory))
continue;
topDirectory = checkDirectory;
fileMoveCollectionDirectory = GetMoveFileCollection(destinationDirectory, topDirectory, group);
results.AddRange(fileMoveCollectionDirectory);
}
return results;
}
private void MoveFiles(List<string> topDirectories, List<Property.Models.Group> groupCollection)
{
if (_Log is null)
throw new Exception($"{nameof(_Log)} is null!");
if (_Configuration?.PropertyConfiguration is null)
throw new Exception($"{nameof(_Configuration.PropertyConfiguration)} must be set!");
string directoryName;
List<string> distinct = new();
List<(string Source, string[] Destination)> fileMoveCollectionAll = GetFileMoveCollectionAll(topDirectories, groupCollection);
foreach ((string source, string[] destination) in fileMoveCollectionAll)
{
directoryName = Path.Combine(destination.Take(destination.Length - 1).ToArray());
if (distinct.Contains(directoryName))
continue;
distinct.Add(directoryName);
if (!Directory.Exists(directoryName))
_ = Directory.CreateDirectory(directoryName);
}
_Log.Information("Ready to move files?");
for (int y = 0; y < int.MaxValue; y++)
{
_Log.Information("Press \"Y\" key to move files back or close console to not move files");
if (Console.ReadKey().Key == ConsoleKey.Y)
break;
}
_Log.Information(". . .");
int moved = 0;
string fullFileName;
foreach ((string source, string[] destination) in fileMoveCollectionAll)
{
fullFileName = Path.Combine(destination);
if (File.Exists(fullFileName))
continue;
File.Move(source, fullFileName);
moved += 1;
}
_Log.Information($"{moved} file(s) moved");
for (int y = 0; y < int.MaxValue; y++)
{
_Log.Information("Press \"Y\" key to move files back or close console to leave them moved");
if (Console.ReadKey().Key == ConsoleKey.Y)
break;
}
_Log.Information(". . .");
foreach ((string source, string[] destination) in fileMoveCollectionAll)
{
fullFileName = Path.Combine(destination);
if (File.Exists(source))
continue;
File.Move(fullFileName, source);
moved += 1;
}
_Log.Information($"Done moving back {moved} file(s)");
for (int i = 1; i < 10; i++)
_ = Property.Models.Stateless.IPath.DeleteEmptyDirectories(_Configuration.PropertyConfiguration.RootDirectory);
}
}

View File

@ -0,0 +1,35 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Date.Group.Models;
public class AppSettings
{
protected string _Company;
protected string _WorkingDirectoryName;
protected int? _MaxDegreeOfParallelism;
public string Company => _Company;
public string WorkingDirectoryName => _WorkingDirectoryName;
public int? MaxDegreeOfParallelism => _MaxDegreeOfParallelism;
// public AppSettings()
// {
// }
[JsonConstructor]
public AppSettings(string company, string workingDirectoryName, int? maxDegreeOfParallelism)
{
_Company = company;
_WorkingDirectoryName = workingDirectoryName;
_MaxDegreeOfParallelism = maxDegreeOfParallelism;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -0,0 +1,26 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
namespace View_by_Distance.Date.Group.Models.Binder;
public class AppSettings
{
[Display(Name = "Company"), Required] public string Company { get; set; }
[Display(Name = "Working Directory Name"), Required] public string WorkingDirectoryName { get; set; }
[Display(Name = "Max Degree Of Parallelism"), Required] public int? MaxDegreeOfParallelism { get; set; }
public AppSettings()
{
Company = string.Empty;
WorkingDirectoryName = string.Empty;
MaxDegreeOfParallelism = -1;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -0,0 +1,30 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
namespace View_by_Distance.Date.Group.Models.Binder;
public class Configuration
{
[Display(Name = "By Date"), Required] public bool? ByDay { get; set; }
[Display(Name = "By Hash"), Required] public bool? ByHash { get; set; }
[Display(Name = "By Season"), Required] public bool? BySeason { get; set; }
[Display(Name = "By Week"), Required] public bool? ByWeek { get; set; }
[Display(Name = "Ignore Subdirectories for Rename"), Required] public bool? KeepFullPath { get; set; }
[Display(Name = "Property Configuration"), Required] public Property.Models.Configuration? PropertyConfiguration { get; set; }
public Configuration()
{
ByDay = null;
ByHash = null;
BySeason = null;
ByWeek = null;
KeepFullPath = null;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -0,0 +1,43 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Date.Group.Models;
public class Configuration
{
protected readonly bool? _ByDay;
protected readonly bool? _ByHash;
protected readonly bool? _BySeason;
protected readonly bool? _ByWeek;
protected readonly bool? _KeepFullPath;
protected Property.Models.Configuration? _PropertyConfiguration;
public bool? ByDay => _ByDay;
public bool? ByHash => _ByHash;
public bool? BySeason => _BySeason;
public bool? ByWeek => _ByWeek;
public bool? KeepFullPath => _KeepFullPath;
public Property.Models.Configuration? PropertyConfiguration => _PropertyConfiguration;
[JsonConstructor]
public Configuration(bool? byDay, bool? byHash, bool? bySeason, bool? byWeek, bool? keepFullPath, Property.Models.Configuration? propertyConfiguration)
{
_ByDay = byDay;
_ByHash = byHash;
_BySeason = bySeason;
_ByWeek = byWeek;
_KeepFullPath = keepFullPath;
_PropertyConfiguration = propertyConfiguration;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
public void Set(Property.Models.Configuration propertyConfiguration) => _PropertyConfiguration = propertyConfiguration;
public void Update() => _PropertyConfiguration?.Update();
}

View File

@ -0,0 +1,40 @@
using Microsoft.Extensions.Configuration;
using System.Text.Json;
namespace View_by_Distance.Date.Group.Models.Stateless;
public abstract class AppSettings
{
public static Models.AppSettings Get(IConfigurationRoot configurationRoot)
{
Models.AppSettings? result;
Binder.AppSettings appSettings = configurationRoot.Get<Binder.AppSettings>();
string json = JsonSerializer.Serialize(appSettings, new JsonSerializerOptions() { WriteIndented = true });
result = JsonSerializer.Deserialize<Models.AppSettings>(json);
if (result is null)
throw new Exception(json);
if (string.IsNullOrEmpty(result.Company))
throw new Exception(json);
string jsonThis = result.ToString();
if (jsonThis != json)
{
int? check = null;
int min = new int[] { json.Length, jsonThis.Length }.Min();
for (int i = 0; i < min; i++)
{
if (json[i] == jsonThis[i])
continue;
check = i;
break;
}
if (check is null)
throw new Exception();
string a = json[..check.Value].Split(',')[^1];
string b = json[check.Value..].Split(',')[0];
throw new Exception($"{a}{b}");
}
return result;
}
}

View File

@ -0,0 +1,44 @@
using Microsoft.Extensions.Configuration;
using Phares.Shared;
using System.Text.Json;
namespace View_by_Distance.Date.Group.Models.Stateless;
public abstract class Configuration
{
public static Models.Configuration Get(IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, string workingDirectory, Property.Models.Configuration propertyConfiguration)
{
Models.Configuration? result;
string environmentName = IsEnvironment.GetEnvironmentName(isEnvironment);
string section = string.Concat(environmentName, ":", nameof(Binder.Configuration));
IConfigurationSection configurationSection = configurationRoot.GetSection(section);
Binder.Configuration configuration = configurationSection.Get<Binder.Configuration>();
string json = JsonSerializer.Serialize(configuration, new JsonSerializerOptions() { WriteIndented = true });
result = JsonSerializer.Deserialize<Models.Configuration>(json);
if (result is null)
throw new Exception(json);
string jsonThis = result.ToString();
result.Set(propertyConfiguration);
result.Update();
if (jsonThis != json)
{
int? check = null;
int min = new int[] { json.Length, jsonThis.Length }.Min();
for (int i = 0; i < min; i++)
{
if (json[i] == jsonThis[i])
continue;
check = i;
break;
}
if (check is null)
throw new Exception();
string a = json[..check.Value].Split(',')[^1];
string b = json[check.Value..].Split(',')[0];
throw new Exception($"{a}{b}");
}
return result;
}
}

View File

@ -0,0 +1,10 @@
namespace View_by_Distance.Date.Group.Models.Stateless;
public static class SerilogExtensionMethods
{
internal static void Warn(this Serilog.ILogger log, string messageTemplate) => log.Warning(messageTemplate);
internal static void Info(this Serilog.ILogger log, string messageTemplate) => log.Information(messageTemplate);
}

109
Date-Group/Program.cs Normal file
View File

@ -0,0 +1,109 @@
using Microsoft.Extensions.Configuration;
using Phares.Shared;
using Serilog;
using System.Diagnostics;
using System.Reflection;
using View_by_Distance.Date.Group.Models;
using View_by_Distance.Shared.Models.Stateless.Methods;
namespace View_by_Distance.Date.Group;
public class Program
{
public static void Secondary(List<string> args)
{
LoggerConfiguration loggerConfiguration = new();
Assembly assembly = Assembly.GetExecutingAssembly();
bool debuggerWasAttachedAtLineZero = Debugger.IsAttached || assembly.Location.Contains(@"\bin\Debug");
IsEnvironment isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero);
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
.AddEnvironmentVariables()
.AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true);
IConfigurationRoot configurationRoot = configurationBuilder.Build();
AppSettings appSettings = Models.Stateless.AppSettings.Get(configurationRoot);
if (appSettings.MaxDegreeOfParallelism is null)
throw new Exception("MaxDegreeOfParallelism must be set!");
if (appSettings.MaxDegreeOfParallelism.Value > Environment.ProcessorCount)
throw new Exception("MaxDegreeOfParallelism must be =< Environment.ProcessorCount!");
if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName))
throw new Exception("Working directory name must have a value!");
string workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName);
Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory);
_ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot);
Log.Logger = loggerConfiguration.CreateLogger();
ILogger log = Log.ForContext<Program>();
int silentIndex = args.IndexOf("s");
if (silentIndex > -1)
args.RemoveAt(silentIndex);
try
{
if (args is null)
throw new Exception("args is null!");
#nullable disable
if (Property.Models.Stateless.A_Property.IsWrongYear("-".Split(' '), "2021").Item1.HasValue)
throw new Exception("-");
if (Property.Models.Stateless.A_Property.IsWrongYear("Christmass".Split(' '), "2021").Item1.HasValue)
throw new Exception("Christmass");
if (Property.Models.Stateless.A_Property.IsWrongYear("Christmass 2021".Split(' '), "2021").Item1.Value)
throw new Exception("Christmass");
if (Property.Models.Stateless.A_Property.IsWrongYear("Christmass ~2021".Split(' '), "2021").Item1.Value)
throw new Exception("Christmass");
if (Property.Models.Stateless.A_Property.IsWrongYear("Christmass ~2021.4".Split(' '), "2021").Item1.Value)
throw new Exception("Christmass");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Christmass 2021".Split(' '), "2025").Item1.Value)
throw new Exception("Christmass");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Christmass ~2021".Split(' '), "2025").Item1.Value)
throw new Exception("Christmass");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Christmass ~2021.4".Split(' '), "2025").Item1.Value)
throw new Exception("Christmass");
if (Property.Models.Stateless.A_Property.IsWrongYear("England 2017".Split(' '), "2017").Item1.Value)
throw new Exception("England");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael".Split(' '), "2021").Item1.HasValue)
throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael 2021".Split(' '), "2021").Item1.Value)
throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021".Split(' '), "2021").Item1.Value)
throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021.4".Split(' '), "2021").Item1.Value)
throw new Exception("Logan Michael");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael 2021".Split(' '), "2025").Item1.Value)
throw new Exception("Logan Michael");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021".Split(' '), "2025").Item1.Value)
throw new Exception("Logan Michael");
if (!Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021.4".Split(' '), "2025").Item1.Value)
throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Logan Michael ~2021.4".Split(' '), "2021").Item2[0] != "~2021.4")
throw new Exception("Logan Michael");
if (Property.Models.Stateless.A_Property.IsWrongYear("Chelsea's 2nd Birthday =2014".Split(' '), "2014").Item1.Value)
throw new Exception("Chelsea");
#nullable restore
Shared.Models.Console console = new();
DateGroup _ = new(args, isEnvironment, configurationRoot, appSettings, workingDirectory, silentIndex > -1, console);
}
catch (Exception ex)
{
log.Fatal(string.Concat(ex.Message, Environment.NewLine, ex.StackTrace));
}
finally
{
Log.CloseAndFlush();
}
if (silentIndex > -1)
log.Debug("Done. Bye");
else
{
log.Debug("Done. Press 'Enter' to end");
_ = Console.ReadLine();
}
}
public static void Main(string[] args)
{
if (args is not null)
Secondary(args.ToList());
else
Secondary(new List<string>());
}
}

View File

@ -0,0 +1,342 @@
{
"Company": "Mike Phares",
"Linux": {},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Log4netProvider": "Debug",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"MaxDegreeOfParallelism": 1,
"Serilog": {
"Using": [
"Serilog.Sinks.Console",
"Serilog.Sinks.File"
],
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "Debug",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
}
},
{
"Name": "Console",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "%workingDirectory% - Log/log-.txt",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}",
"rollingInterval": "Hour"
}
}
],
"Enrich": [
"FromLogContext",
"WithMachineName",
"WithThreadId"
],
"Properties": {
"Application": "Sample"
}
},
"WorkingDirectoryName": "PharesApps",
"Windows": {
"Configuration": {
"ByDay": false,
"ByHash": false,
"BySeason": true,
"ByWeek": false,
"DateGroup": "2022-04-07",
"FileNameDirectorySeparator": ".Z.",
"ForcePropertyLastWriteTimeToCreationTime": false,
"KeepFullPath": false,
"MaxImagesInDirectoryForTopLevelFirstPass": 50,
"Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]",
"PopulatePropertyId": false,
"PropertiesChangedForProperty": false,
"RootDirectory": "C:/Tmp/Phares/- Device Videos 2_0_0_3 - Current/_",
"WriteBitmapDataBytes": false,
"IgnoreExtensions": [
".gif",
".GIF"
],
"PropertyContentCollectionFiles": [],
"ValidImageFormatExtensions": [
".bmp",
".BMP",
".gif",
".GIF",
".jpeg",
".JPEG",
".jpg",
".JPG",
".png",
".PNG",
".tiff",
".TIFF"
],
"ValidMetadataExtensions": [
".3gp",
".3GP",
".amr",
".AMR",
".avi",
".AVI",
".bmp",
".BMP",
".gif",
".GIF",
".ico",
".ICO",
".jpeg",
".JPEG",
".jpg",
".JPG",
".m4v",
".M4V",
".mov",
".MOV",
".mp4",
".MP4",
".mta",
".MTA",
".png",
".PNG",
".tiff",
".TIFF"
],
"VerifyToSeason": [
". 2000",
". 2001",
". 2002",
". 2003",
". 2004",
". 2005",
". 2006",
". 2007",
". 2008",
". 2009",
". 2010",
". 2011",
". 2012",
". 2013",
". 2014",
". 2015",
". 2016",
". 2017",
". 2018",
". 2019",
". 2020",
". 2021",
". 2022",
". 2023",
". 2024",
". 2025",
". 2026",
". 2027",
". 2028",
". 2029",
"=2000.0 Winter",
"=2002.1 Spring",
"=2002.4 Winter",
"=2003.0 Winter",
"=2003.1 Spring",
"=2003.3 Fall",
"=2003.4 Winter",
"=2004.0 Winter",
"=2005.1 Spring",
"=2005.2 Summer",
"=2005.3 Fall",
"=2005.4 Winter",
"=2006.0 Winter",
"=2006.1 Spring",
"=2006.3 Fall",
"=2007.0 Winter",
"=2007.2 Summer Logan Michael",
"=2007.2 Summer",
"=2007.3 Fall Logan Michael",
"=2007.4 Winter Logan Michael",
"=2008.0 Winter Logan Michael",
"=2008.1 Spring Logan Michael",
"=2008.2 Summer Logan Michael",
"=2008.2 Summer",
"=2008.3 Fall Logan Michael",
"=2009.0 Winter Logan Michael",
"=2009.0 Winter",
"=2009.1 Spring Logan Michael",
"=2009.1 Spring",
"=2009.2 Summer Logan Michael",
"=2009.2 Summer",
"=2009.3 Fall Logan Michael",
"=2009.3 Fall",
"=2009.4 Winter Logan Michael",
"=2009.4 Winter",
"=2010.0 Winter Logan Michael",
"=2010.0 Winter",
"=2010.1 Spring Logan Michael",
"=2010.1 Spring",
"=2010.2 Summer",
"=2010.3 Fall Logan Michael",
"=2010.3 Fall",
"=2010.4 Winter",
"=2011.0 Winter",
"=2011.1 Spring",
"=2011.2 Summer",
"=2011.3 Fall",
"=2011.4 Winter",
"=2012.0 Winter Chelsea 2012",
"=2012.0 Winter Chelsea",
"=2012.0 Winter",
"=2012.1 Spring Chelsea",
"=2012.1 Spring",
"=2012.2 Summer Chelsea",
"=2012.2 Summer",
"=2012.3 Fall Chelsea",
"=2012.3 Fall",
"=2012.4 Winter Chelsea",
"=2012.4 Winter",
"=2013.0 Winter Chelsea 2013",
"=2013.0 Winter Chelsea",
"=2013.0 Winter",
"=2013.1 Spring",
"=2013.2 Summer Chelsea",
"=2013.2 Summer",
"=2013.3 Fall Chelsea",
"=2013.3 Fall",
"=2013.4 Winter",
"=2014.0 Winter",
"=2014.1 Spring",
"=2014.2 Summer",
"=2014.3 Fall",
"=2014.4 Winter",
"=2015.0 Winter",
"=2015.1 Spring",
"=2015.2 Summer",
"=2015.3 Fall",
"=2015.4 Winter",
"=2016.0 Winter",
"=2016.1 Spring",
"=2016.2 Summer",
"=2016.3 Fall",
"=2016.4 Winter",
"=2017.1 Spring",
"=2017.2 Summer",
"=2017.3 Fall",
"=2017.4 Winter",
"=2018.0 Winter",
"=2018.1 Spring",
"=2018.3 Fall",
"=2018.4 Winter",
"=2019.0 Winter",
"=2019.1 Spring",
"=2019.2 Summer",
"=2019.3 Fall",
"=2019.4 Winter",
"=2020.0 Winter",
"=2020.1 Spring",
"=2020.2 Summer",
"=2020.3 Fall",
"=2020.4 Winter",
"=2021.1 Spring",
"=2021.2 Summer",
"=2021.3 Fall",
"=2021.4 Winter",
"=2022.0 Winter",
"=2022.1 Spring",
"Anthem 2015",
"April 2010",
"April 2013",
"December 2006",
"December 2010",
"Fall 2005",
"Fall 2015",
"Fall 2016",
"Fall 2017",
"Fall 2018",
"Fall 2019",
"Fall 2020",
"Fall 2021",
"February 2010",
"January 2015",
"July 2010",
"June 2010",
"Kids 2005",
"March 2013",
"May 2010",
"May 2011",
"May 2013",
"October 2005",
"October 2014",
"Spring 2013",
"Spring 2014",
"Spring 2016",
"Spring 2018",
"Spring 2019",
"Spring 2020",
"Summer 2011",
"Summer 2012",
"Summer 2013",
"Summer 2014",
"Summer 2015",
"Summer 2016",
"Summer 2017",
"Summer 2018",
"Summer 2020",
"Summer 2021",
"Winter 2015",
"Winter 2016",
"Winter 2017",
"Winter 2018",
"Winter 2019-2020",
"Winter 2020",
"zzz =2005.0 Winter Tracy Pictures",
"zzz =2005.1 Spring Tracy Pictures",
"zzz =2005.2 Summer Tracy Pictures",
"zzz =2005.3 Fall Tracy Pictures",
"zzz =2005.4 Winter Tracy Pictures",
"zzz =2006.1 Spring Tracy Pictures",
"zzz =2007.0 Winter Tracy Pictures",
"zzz =2007.2 Summer Tracy Pictures",
"zzz =2008.0 Winter Tracy Pictures",
"zzz =2008.2 Summer Tracy Pictures",
"zzz =2009.0 Winter Tracy Pictures",
"zzz =2009.2 Summer Tracy Pictures",
"zzz =2009.3 Fall Tracy Pictures",
"zzz =2009.4 Winter Tracy Pictures",
"zzz =2010.0 Winter Tracy Pictures",
"zzz =2010.1 Spring Tracy Pictures",
"zzz =2010.2 Summer Tracy Pictures",
"zzz =2010.3 Fall Tracy Pictures",
"zzz =2011.0 Winter Tracy Pictures",
"zzz =2011.1 Spring Tracy Pictures",
"zzz =2011.2 Summer Tracy Pictures",
"zzz =2011.3 Fall Tracy Pictures",
"zzz =2011.4 Winter Tracy Pictures",
"zzz =2012.0 Winter Tracy Pictures",
"zzz =2012.1 Spring Tracy Pictures",
"zzz =2012.2 Summer Tracy Pictures",
"zzz =2012.3 Fall Tracy Pictures",
"zzz =2012.4 Winter Tracy Pictures",
"zzz =2013.0 Winter Tracy Pictures",
"zzz =2013.1 Spring Tracy Pictures",
"zzz =2013.2 Summer Tracy Pictures",
"zzz =2013.3 Fall Tracy Pictures",
"zzz =2013.4 Winter Tracy Pictures",
"zzz =2014.0 Winter Tracy Pictures",
"zzz =2014.1 Spring Tracy Pictures",
"zzz =2014.2 Summer Tracy Pictures",
"zzz =2014.3 Fall Tracy Pictures",
"zzz =2014.4 Winter Tracy Pictures",
"zzz =2015.0 Winter Tracy Pictures"
]
}
}
}