IntelligentIdRecord

This commit is contained in:
Mike Phares 2023-12-22 15:46:47 -07:00
parent 0310e06f3c
commit 96c479e639
8 changed files with 140 additions and 89 deletions

View File

@ -147,7 +147,7 @@ public class A_Metadata
ReadOnlyCollection<string> ffmpegFiles;
DeterministicHashCode deterministicHashCode;
FilePath filePath = IId.GetFilePath(renameConfiguration.MetadataConfiguration, file);
if (!renameConfiguration.SkipIdFiles || filePath.Id is null || !filePath.IsIdFormat && !filePath.IsPaddedIdFormat)
if (!renameConfiguration.SkipIdFiles || filePath.Id is null || !filePath.IsIntelligentIdFormat && filePath.SortOrder is not null)
{
(ffmpegFiles, ffmpegFilePath) = rename.ConvertAndGetFfmpegFiles(renameConfiguration, filePath);
if (ffmpegFilePath is not null)

View File

@ -9,6 +9,7 @@ public class MetadataConfiguration
public bool? ForceMetadataLastWriteTimeToCreationTime { get; set; }
public string[]? IgnoreRulesKeyWords { get; set; }
public int? IntMinValueLength { get; set; }
public int? Offset { get; set; }
public bool? PropertiesChangedForMetadata { get; set; }
@ -38,6 +39,7 @@ public class MetadataConfiguration
private static void Verify(MetadataConfiguration configuration)
{
if (configuration.IntMinValueLength is null || configuration.IntMinValueLength != int.MinValue.ToString().Length) throw new NotSupportedException(nameof(configuration.IgnoreRulesKeyWords));
if (configuration.IgnoreRulesKeyWords is null || configuration.IgnoreRulesKeyWords.Length == 0) throw new NullReferenceException(nameof(configuration.IgnoreRulesKeyWords));
}
@ -46,6 +48,7 @@ public class MetadataConfiguration
Shared.Models.MetadataConfiguration result;
if (configuration is null) throw new NullReferenceException(nameof(configuration));
if (configuration.ForceMetadataLastWriteTimeToCreationTime is null) throw new NullReferenceException(nameof(configuration.ForceMetadataLastWriteTimeToCreationTime));
if (configuration.IntMinValueLength is null) throw new NullReferenceException(nameof(configuration.IntMinValueLength));
if (configuration.IgnoreRulesKeyWords is null) throw new NullReferenceException(nameof(configuration.IgnoreRulesKeyWords));
if (configuration.Offset is null) throw new NullReferenceException(nameof(configuration.Offset));
if (configuration.PropertiesChangedForMetadata is null) throw new NullReferenceException(nameof(configuration.PropertiesChangedForMetadata));
@ -53,6 +56,7 @@ public class MetadataConfiguration
result = new(resultConfiguration,
configuration.ForceMetadataLastWriteTimeToCreationTime.Value,
configuration.IgnoreRulesKeyWords,
configuration.IntMinValueLength.Value,
configuration.Offset.Value,
configuration.PropertiesChangedForMetadata.Value);
return result;

View File

@ -54,8 +54,7 @@ public class Rename : IRename
else
{
CommandTask<CommandResult> commandTask = Cli.Wrap("ffmpeg.exe")
// .WithArguments(new[] { "-ss", "00:00:00", "-t", "00:00:00", "-i", files[i], "-qScale:v", "2", "-r", "0.01", $"{fileHolder.Name}-%4d.jpg" })
.WithArguments(new[] { "-i", filePath.FullName, "-vFrames", "1", $"{filePath.Name}-%4d.jpg" })
.WithArguments(new[] { "-i", filePath.FullName, "-vf", "select=eq(n\\,0)", "-q:v", "1", $"{filePath.Name}-%4d.jpg" })
.WithWorkingDirectory(filePath.DirectoryName)
.ExecuteAsync();
commandTask.Task.Wait();
@ -122,7 +121,7 @@ public class Rename : IRename
{
rename.Tick();
filePath = IId.GetFilePath(renameConfiguration.MetadataConfiguration, file);
if (renameConfiguration.SkipIdFiles && filePath.Id is not null && (filePath.IsIdFormat || filePath.IsPaddedIdFormat))
if (renameConfiguration.SkipIdFiles && filePath.Id is not null && (filePath.IsIntelligentIdFormat || filePath.SortOrder is not null))
continue;
(ffmpegFiles, ffmpegFilePath) = rename.ConvertAndGetFfmpegFiles(renameConfiguration, filePath);
if (ffmpegFilePath is not null)
@ -173,13 +172,13 @@ public class Rename : IRename
return results;
}
private static void VerifyIntMinValueLength(ReadOnlyCollection<Record> exifDirectories, int intMinValueLength)
private static void VerifyIntMinValueLength(MetadataConfiguration metadataConfiguration, ReadOnlyCollection<Record> exifDirectories)
{
foreach ((DateTime _, ExifDirectory exifDirectory, string _, string _) in exifDirectories)
{
if (exifDirectory.Id is null)
continue;
if (intMinValueLength < exifDirectory.Id.Value.ToString().Length)
if (metadataConfiguration.IntMinValueLength < exifDirectory.Id.Value.ToString().Length)
throw new NotSupportedException();
}
}
@ -189,11 +188,20 @@ public class Rename : IRename
string? checkDirectory;
if (fileHolder.DirectoryName is null)
throw new NullReferenceException(nameof(fileHolder.DirectoryName));
(int season, string seasonName) = IDate.GetSeason(record.DateTime.DayOfYear);
string directoryName;
string year = record.DateTime.Year.ToString();
string checkDirectoryName = Path.GetFileName(fileHolder.DirectoryName);
if (!checkDirectoryName.Contains(year))
throw new NotImplementedException();
else
{
string maker = IMetadata.GetMaker(record.ExifDirectory.ExifDirectoryBase);
(int seasonValue, string seasonName) = IDate.GetSeason(record.DateTime.DayOfYear);
string splat = fileHolder.DirectoryName[^3..][1] == '!' ? fileHolder.DirectoryName[^3..] : string.Empty;
directoryName = $"{year}.{seasonValue} {seasonName} {maker.Split(' ')[0]}{splat}";
}
string rootDirectory = renameConfiguration.MoveFilesToRoot ? renameConfiguration.MetadataConfiguration.ResultConfiguration.RootDirectory : fileHolder.DirectoryName;
checkDirectory = Path.Combine(rootDirectory, "_ Destination _", $"{record.DateTime.Year}.{season} {seasonName} {maker.Split(' ')[0]}{splat}");
checkDirectory = Path.Combine(rootDirectory, "_ Destination _", directoryName);
return checkDirectory;
}
@ -212,8 +220,7 @@ public class Rename : IRename
List<string> distinct = [];
const string jpeg = ".jpeg";
string jsonFileSubDirectory;
int intMinValueLength = int.MinValue.ToString().Length;
VerifyIntMinValueLength(exifDirectories, intMinValueLength);
VerifyIntMinValueLength(renameConfiguration.MetadataConfiguration, exifDirectories);
ResultConfiguration resultConfiguration = renameConfiguration.MetadataConfiguration.ResultConfiguration;
ReadOnlyCollection<Record> records = new((from l in exifDirectories orderby l.DateTime select l).ToArray());
for (int i = 0; i < records.Count; i++)
@ -226,8 +233,8 @@ public class Rename : IRename
continue;
checkDirectory = GetCheckDirectory(renameConfiguration, record, fileHolder);
checkFileExtension = fileHolder.ExtensionLowered == jpeg ? jpg : fileHolder.ExtensionLowered;
paddedId = IId.GetPaddedId(renameConfiguration.MetadataConfiguration, i, record.ExifDirectory.Id.Value);
jsonFileSubDirectory = Path.GetDirectoryName(Path.GetDirectoryName(record.JsonFile)) ?? throw new Exception();
paddedId = IId.GetPaddedId(intMinValueLength, renameConfiguration.MetadataConfiguration.Offset + i, record.ExifDirectory.Id.Value);
checkFile = Path.Combine(checkDirectory, $"{paddedId}{checkFileExtension}");
if (checkFile == fileHolder.FullName)
continue;

View File

@ -5,12 +5,13 @@ namespace View_by_Distance.Shared.Models;
public record FilePath(string DirectoryName,
string ExtensionLowered,
string FileNameFirstSegment,
string FullName,
int? Id,
bool IsIdFormat,
bool IsPaddedIdFormat,
bool IsIntelligentIdFormat,
string Name,
string NameWithoutExtension)
string NameWithoutExtension,
int? SortOrder)
{
public override string ToString()

View File

@ -0,0 +1,24 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace View_by_Distance.Shared.Models;
public record IntelligentIdRecord(int Key,
char GroupChar2,
char GroupChar1,
string Reverse)
{
public override string ToString()
{
string result = JsonSerializer.Serialize(this, IntelligentIdRecordSourceGenerationContext.Default.IntelligentIdRecord);
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(IntelligentIdRecord))]
internal partial class IntelligentIdRecordSourceGenerationContext : JsonSerializerContext
{
}

View File

@ -6,6 +6,7 @@ namespace View_by_Distance.Shared.Models;
public record MetadataConfiguration(ResultConfiguration ResultConfiguration,
bool ForceMetadataLastWriteTimeToCreationTime,
string[] IgnoreRulesKeyWords,
int IntMinValueLength,
int Offset,
bool PropertiesChangedForMetadata)
{

View File

@ -1,3 +1,4 @@
using System.Text;
using View_by_Distance.Shared.Models.Stateless.Methods;
namespace View_by_Distance.Shared.Models.Stateless;
@ -5,26 +6,59 @@ namespace View_by_Distance.Shared.Models.Stateless;
internal abstract class Id
{
internal static bool NameWithoutExtensionIsIdFormat(string fileNameWithoutExtension)
private static int GetId(MetadataConfiguration metadataConfiguration, string intelligentId)
{
bool result;
int intMinValueLength = int.MinValue.ToString().Length;
if (fileNameWithoutExtension.Length < 5 || fileNameWithoutExtension.Length > intMinValueLength)
result = false;
else
{
bool skipOneAllAreNumbers = fileNameWithoutExtension[1..].All(l => char.IsNumber(l));
result = (skipOneAllAreNumbers && fileNameWithoutExtension[0] == '-') || (skipOneAllAreNumbers && char.IsNumber(fileNameWithoutExtension[0]));
}
int result;
StringBuilder results = new();
if (metadataConfiguration.IntMinValueLength < 4)
throw new NotSupportedException();
for (int j = intelligentId.Length - 4; j > -1; j--)
_ = results.Append(intelligentId[j]);
_ = results.Append(intelligentId[^3]).Append(intelligentId[^2]);
result = int.Parse(results.ToString());
if (intelligentId[^1] is '1' or '2')
result *= -1;
else if (intelligentId[^1] is not '9' and not '8')
throw new NotSupportedException();
return result;
}
internal static FilePath GetFilePath(FilePath filePath, string file)
private static IntelligentIdRecord GetIntelligentIdRecord(MetadataConfiguration metadataConfiguration, long id, bool ignore)
{
FilePath result;
string fileName = Path.GetFileName(file);
string fileExtensionLowered = Path.GetExtension(file).ToLower();
result = new(filePath.DirectoryName, fileExtensionLowered, file, filePath.Id, filePath.IsIdFormat, filePath.IsPaddedIdFormat, fileName, filePath.NameWithoutExtension);
IntelligentIdRecord result;
StringBuilder stringBuilder = new();
if (metadataConfiguration.IntMinValueLength < 4)
throw new NotSupportedException();
int key;
string value;
if (id > -1)
{
key = ignore ? 8 : 9;
value = id.ToString().PadLeft(metadataConfiguration.IntMinValueLength, '0');
}
else
{
key = ignore ? 2 : 1;
value = id.ToString()[1..].PadLeft(metadataConfiguration.IntMinValueLength, '0');
}
for (int j = value.Length - 3; j > -1; j--)
_ = stringBuilder.Append(value[j]);
result = new(key, value[^2], value[^1], stringBuilder.ToString());
return result;
}
private static string GetIntelligentId(IntelligentIdRecord intelligentId) =>
$"{intelligentId.Reverse}{intelligentId.GroupChar2}{intelligentId.GroupChar1}{intelligentId.Key}";
internal static string GetPaddedId(MetadataConfiguration metadataConfiguration, int index, int id)
{
string result;
IntelligentIdRecord intelligentIdRecord = GetIntelligentIdRecord(metadataConfiguration, id, ignore: false);
string intelligentId = GetIntelligentId(intelligentIdRecord);
int check = GetId(metadataConfiguration, intelligentId);
if (check != id)
throw new NotSupportedException();
result = $"{metadataConfiguration.Offset + index}{intelligentId}";
return result;
}
@ -32,44 +66,30 @@ internal abstract class Id
{
FilePath result;
int? id;
short? multiplier;
char negativeMarker;
int absoluteValueOfId;
int? sortOder;
string fileName = Path.GetFileName(file);
string[] segments = Path.GetFileName(fileName).Split('.');
string fileExtensionLowered = Path.GetExtension(file).ToLower();
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file);
string fileDirectoryName = Path.GetDirectoryName(file) ?? throw new NullReferenceException();
short sortOrderOnlyLengthIndex = IId.GetSortOrderOnlyLengthIndex(metadataConfiguration.Offset);
bool nameWithoutExtensionIsIdFormat = IId.NameWithoutExtensionIsIdFormat(fileNameWithoutExtension);
bool nameWithoutExtensionIsPaddedIdFormat = IId.NameWithoutExtensionIsPaddedIdFormat(fileNameWithoutExtension, sortOrderOnlyLengthIndex);
if (!nameWithoutExtensionIsIdFormat && !nameWithoutExtensionIsPaddedIdFormat)
id = null;
else if (nameWithoutExtensionIsIdFormat)
short sortOrderOnlyLengthIndex = IId.GetSortOrderOnlyLengthIndex(metadataConfiguration);
string fileNameFirstSegment = segments[0];
bool fileNameFirstSegmentIsIntelligentIdFormat = IId.NameWithoutExtensionIsIntelligentIdFormat(metadataConfiguration, fileNameFirstSegment);
bool fileNameFirstSegmentIsPaddedIntelligentIdFormat = IId.NameWithoutExtensionIsPaddedIntelligentIdFormat(metadataConfiguration, sortOrderOnlyLengthIndex, fileNameFirstSegment);
if (!fileNameFirstSegmentIsIntelligentIdFormat && !fileNameFirstSegmentIsPaddedIntelligentIdFormat)
(id, sortOder) = (null, null);
else if (fileNameFirstSegmentIsIntelligentIdFormat)
(id, sortOder) = (GetId(metadataConfiguration, fileNameFirstSegment), null);
else if (fileNameFirstSegmentIsPaddedIntelligentIdFormat)
{
if (!int.TryParse(fileNameWithoutExtension, out absoluteValueOfId))
id = null;
if (!int.TryParse(fileNameFirstSegment[..sortOrderOnlyLengthIndex], out int absoluteValueOfSortOrder))
(id, sortOder) = (null, null);
else
id = absoluteValueOfId;
(id, sortOder) = (GetId(metadataConfiguration, fileNameFirstSegment[sortOrderOnlyLengthIndex..]), absoluteValueOfSortOrder);
}
else
{
negativeMarker = fileNameWithoutExtension[sortOrderOnlyLengthIndex - 2];
if (negativeMarker == '7')
multiplier = 1;
else if (negativeMarker == '3')
multiplier = -1;
else
multiplier = null;
if (!int.TryParse(fileNameWithoutExtension[sortOrderOnlyLengthIndex..], out absoluteValueOfId))
id = null;
else
{
id = absoluteValueOfId * multiplier;
if (id is null || !fileNameWithoutExtension.EndsWith(id.Value.ToString()[1..]))
id = null;
}
}
result = new(fileDirectoryName, fileExtensionLowered, file, id, nameWithoutExtensionIsIdFormat, nameWithoutExtensionIsPaddedIdFormat, fileName, fileNameWithoutExtension);
throw new NotSupportedException();
result = new(fileDirectoryName, fileExtensionLowered, fileNameFirstSegment, file, id, fileNameFirstSegmentIsIntelligentIdFormat, fileName, fileNameWithoutExtension, sortOder);
return result;
}

View File

@ -3,38 +3,32 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods;
public interface IId
{
bool TestStatic_NameWithoutExtensionIsIdFormat(string fileNameWithoutExtension) =>
NameWithoutExtensionIsIdFormat(fileNameWithoutExtension);
static bool NameWithoutExtensionIsIdFormat(string fileNameWithoutExtension) =>
Id.NameWithoutExtensionIsIdFormat(fileNameWithoutExtension);
string TestStatic_GetIntelligentId(IntelligentIdRecord intelligentId) =>
GetIntelligentId(intelligentId);
static string GetIntelligentId(IntelligentIdRecord intelligentId) =>
$"{intelligentId.Reverse}{intelligentId.GroupChar2}{intelligentId.GroupChar1}{intelligentId.Key}";
bool TestStatic_NameWithoutExtensionIsIdFormat(FileHolder fileHolder) =>
NameWithoutExtensionIsIdFormat(fileHolder);
static bool NameWithoutExtensionIsIdFormat(FileHolder fileHolder) =>
NameWithoutExtensionIsIdFormat(fileHolder.NameWithoutExtension);
string TestStatic_GetPaddedId(MetadataConfiguration metadataConfiguration, int index, int id) =>
GetPaddedId(metadataConfiguration, index, id);
static string GetPaddedId(MetadataConfiguration metadataConfiguration, int index, int id) =>
Id.GetPaddedId(metadataConfiguration, index, id);
string TestStatic_GetPaddedId(int intMinValueLength, int index, int id) =>
GetPaddedId(intMinValueLength, index, id);
static string GetPaddedId(int intMinValueLength, int index, int id) =>
id > -1 ? $"{index}070{id.ToString().PadLeft(intMinValueLength, '0')}" : $"{index}030{id.ToString()[1..].PadLeft(intMinValueLength, '0')}";
bool TestStatic_NameWithoutExtensionIsIntelligentIdFormat(MetadataConfiguration metadataConfiguration, string fileNameFirstSegment) =>
NameWithoutExtensionIsIntelligentIdFormat(metadataConfiguration, fileNameFirstSegment);
static bool NameWithoutExtensionIsIntelligentIdFormat(MetadataConfiguration metadataConfiguration, string fileNameFirstSegment) =>
fileNameFirstSegment.Length - 1 == metadataConfiguration.IntMinValueLength && fileNameFirstSegment[^1] is '1' or '2' or '8' or '9' && fileNameFirstSegment.All(char.IsNumber);
bool TestStatic_NameWithoutExtensionIsPaddedIdFormat(string fileNameWithoutExtension, short sortOrderOnlyLengthIndex) =>
NameWithoutExtensionIsPaddedIdFormat(fileNameWithoutExtension, sortOrderOnlyLengthIndex);
static bool NameWithoutExtensionIsPaddedIdFormat(string fileNameWithoutExtension, short sortOrderOnlyLengthIndex) =>
fileNameWithoutExtension.Length > sortOrderOnlyLengthIndex
&& fileNameWithoutExtension[sortOrderOnlyLengthIndex] == '0'
&& fileNameWithoutExtension[sortOrderOnlyLengthIndex - 3] == '0'
&& fileNameWithoutExtension.All(l => char.IsNumber(l));
bool TestStatic_NameWithoutExtensionIsPaddedIntelligentIdFormat(MetadataConfiguration metadataConfiguration, short sortOrderOnlyLengthIndex, string fileNameFirstSegment) =>
NameWithoutExtensionIsPaddedIntelligentIdFormat(metadataConfiguration, sortOrderOnlyLengthIndex, fileNameFirstSegment);
static bool NameWithoutExtensionIsPaddedIntelligentIdFormat(MetadataConfiguration metadataConfiguration, short sortOrderOnlyLengthIndex, string fileNameFirstSegment) =>
fileNameFirstSegment.Length == metadataConfiguration.IntMinValueLength + sortOrderOnlyLengthIndex + 1
&& fileNameFirstSegment[^1] is '1' or '2' or '8' or '9'
&& fileNameFirstSegment.All(char.IsNumber);
short TestStatic_GetSortOrderOnlyLengthIndex(int offset) =>
GetSortOrderOnlyLengthIndex(offset);
static short GetSortOrderOnlyLengthIndex(int offset) =>
(short)(offset.ToString().Length + 3);
FilePath TestStatic_GetFilePath(FilePath filePath, string file) =>
GetFilePath(filePath, file);
static FilePath GetFilePath(FilePath filePath, string file) =>
Id.GetFilePath(filePath, file);
short TestStatic_GetSortOrderOnlyLengthIndex(MetadataConfiguration metadataConfiguration) =>
GetSortOrderOnlyLengthIndex(metadataConfiguration);
static short GetSortOrderOnlyLengthIndex(MetadataConfiguration metadataConfiguration) =>
(short)metadataConfiguration.Offset.ToString().Length;
FilePath TestStatic_GetFilePath(MetadataConfiguration metadataConfiguration, string file) =>
GetFilePath(metadataConfiguration, file);