person-key-to-immich-import birthday json (Day-Helper-2024-05-18)

csharp_prefer_braces = true
This commit is contained in:
2025-09-06 11:16:55 -07:00
parent 8ec89953bc
commit 6102da7266
54 changed files with 2218 additions and 1721 deletions

View File

@ -28,7 +28,7 @@ csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_open_brace = none
csharp_new_line_between_query_expression_clauses = true
csharp_prefer_braces = false
csharp_prefer_braces = true
csharp_prefer_qualified_reference = true:error
csharp_prefer_simple_default_expression = true:warning
csharp_prefer_simple_using_statement = true:warning

View File

@ -5,41 +5,6 @@ namespace File_Folder_Helper.ADO2025.PI4;
internal static partial class Helper20250101 {
private static ReadOnlyDictionary<string, List<FileInfo>> GetKeyValuePairs(string directory, string searchPattern, string split) {
string key;
List<FileInfo>? collection;
Dictionary<string, List<FileInfo>> results = [];
string[] files = Directory.GetFiles(directory, searchPattern, SearchOption.TopDirectoryOnly);
FileInfo[] fileInfoCollection = files.Select(l => new FileInfo(l)).ToArray();
foreach (FileInfo fileInfo in fileInfoCollection.OrderBy(l => l.LastWriteTime)) {
key = fileInfo.Name.Split(split)[0];
if (!results.TryGetValue(key, out collection)) {
results.Add(key, []);
if (!results.TryGetValue(key, out collection))
throw new Exception();
}
collection.Add(fileInfo);
}
return results.AsReadOnly();
}
private static void MoveToDelete(ILogger<Worker> logger, string appendage, ReadOnlyDictionary<string, List<FileInfo>> keyValuePairs) {
string checkFile;
FileInfo fileInfo;
foreach (KeyValuePair<string, List<FileInfo>> keyValuePair in keyValuePairs) {
if (keyValuePair.Value.Count < 3)
continue;
for (int i = 1; i < keyValuePair.Value.Count - 1; i++) {
fileInfo = keyValuePair.Value[i];
checkFile = Path.Combine($"{fileInfo.Directory}{appendage}", fileInfo.Name);
if (File.Exists(checkFile))
continue;
logger.LogInformation("Moving <{fileInfo.FullName}> to <{checkFile}>", fileInfo.FullName, checkFile);
File.Move(fileInfo.FullName, checkFile);
}
}
}
internal static void MoveToDelete(ILogger<Worker> logger, List<string> args) {
string split = args[3];
string appendage = args[4];
@ -50,4 +15,42 @@ internal static partial class Helper20250101 {
MoveToDelete(logger, appendage, keyValuePairs);
}
private static ReadOnlyDictionary<string, List<FileInfo>> GetKeyValuePairs(string directory, string searchPattern, string split) {
string key;
List<FileInfo>? collection;
Dictionary<string, List<FileInfo>> results = [];
string[] files = Directory.GetFiles(directory, searchPattern, SearchOption.TopDirectoryOnly);
FileInfo[] fileInfoCollection = files.Select(l => new FileInfo(l)).ToArray();
foreach (FileInfo fileInfo in fileInfoCollection.OrderBy(l => l.LastWriteTime)) {
key = fileInfo.Name.Split(split)[0];
if (!results.TryGetValue(key, out collection)) {
results.Add(key, []);
if (!results.TryGetValue(key, out collection)) {
throw new Exception();
}
}
collection.Add(fileInfo);
}
return results.AsReadOnly();
}
private static void MoveToDelete(ILogger<Worker> logger, string appendage, ReadOnlyDictionary<string, List<FileInfo>> keyValuePairs) {
string checkFile;
FileInfo fileInfo;
foreach (KeyValuePair<string, List<FileInfo>> keyValuePair in keyValuePairs) {
if (keyValuePair.Value.Count < 3) {
continue;
}
for (int i = 1; i < keyValuePair.Value.Count - 1; i++) {
fileInfo = keyValuePair.Value[i];
checkFile = Path.Combine($"{fileInfo.Directory}{appendage}", fileInfo.Name);
if (File.Exists(checkFile)) {
continue;
}
logger.LogInformation("Moving <{fileInfo.FullName}> to <{checkFile}>", fileInfo.FullName, checkFile);
File.Move(fileInfo.FullName, checkFile);
}
}
}
}

View File

@ -4,6 +4,15 @@ namespace File_Folder_Helper.ADO2025.PI4;
internal static partial class Helper20250114 {
internal static void Rename(ILogger<Worker> logger, List<string> args) {
string dateFormat = args[3];
string[] searchPatterns = args[2].Split('~');
string sourceDirectory = Path.GetFullPath(args[0]);
foreach (string searchPattern in searchPatterns) {
Rename(logger, sourceDirectory, searchPattern, dateFormat);
}
}
private static void Rename(string[] directories, string dateFormat) {
string[] files;
DateTime dateTime;
@ -14,16 +23,19 @@ internal static partial class Helper20250114 {
files = Directory.GetFiles(directory, "*", SearchOption.AllDirectories);
foreach (string file in files) {
fileInfo = new(file);
if (dateTime > fileInfo.LastWriteTime)
if (dateTime > fileInfo.LastWriteTime) {
continue;
}
dateTime = fileInfo.LastWriteTime;
}
if (dateTime == DateTime.MinValue)
if (dateTime == DateTime.MinValue) {
continue;
}
checkDirectory = Path.Combine(Path.GetDirectoryName(directory) ?? throw new Exception(), dateTime.ToString(dateFormat));
if (checkDirectory != directory) {
if (Directory.Exists(checkDirectory))
if (Directory.Exists(checkDirectory)) {
continue;
}
Directory.Move(directory, checkDirectory);
}
Directory.SetLastWriteTime(checkDirectory, dateTime);
@ -36,12 +48,4 @@ internal static partial class Helper20250114 {
Rename(directories, dateFormat);
}
internal static void Rename(ILogger<Worker> logger, List<string> args) {
string dateFormat = args[3];
string[] searchPatterns = args[2].Split('~');
string sourceDirectory = Path.GetFullPath(args[0]);
foreach (string searchPattern in searchPatterns)
Rename(logger, sourceDirectory, searchPattern, dateFormat);
}
}

View File

@ -6,62 +6,6 @@ namespace File_Folder_Helper.ADO2025.PI4;
internal static partial class Helper20250126 {
private static void Move(string file, string fileName, string checkFile, List<string> foundLines, ReadOnlyCollection<DateTime> dateTimes) {
string checkDirectory = Path.Combine(Path.GetDirectoryName(file) ?? throw new Exception(), dateTimes[0].ToString("yyyy-MM"));
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
string fileNameB = Path.GetFileName(checkFile);
string checkFileB = Path.Combine(checkDirectory, fileName);
string checkFileC = Path.Combine(checkDirectory, fileNameB);
string contents = string.Join(Environment.NewLine, foundLines);
string checkFileD = Path.Combine(checkDirectory, $"{fileName}.txt");
if (!File.Exists(checkFileB))
File.Move(file, checkFileB);
if (!File.Exists(checkFileC))
File.Move(checkFile, checkFileC);
File.WriteAllText(checkFileD, contents);
}
private static void Move(ILogger<Worker> logger, string dateFormat, string file, string checkFile, string fileName, ReadOnlyCollection<string> statementPeriodSegments, List<string> foundLines) {
DateTime dateTime;
List<DateTime> dateTimes = [];
foreach (string check in statementPeriodSegments) {
if (!DateTime.TryParseExact(check, dateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
continue;
dateTimes.Add(dateTime);
}
if (dateTimes.Count != 2)
logger.LogInformation($"Only {dateTimes.Count} date(s) were found in <{fileName}>!");
else
Move(file, fileName, checkFile, foundLines, dateTimes.AsReadOnly());
}
private static void Move(ILogger<Worker> logger, string file, string checkFile, string dateFormat, string statementPeriod, string search) {
List<string> foundLines = [];
bool statementPeriodFound = false;
string[]? statementPeriodSegments = null;
string fileName = Path.GetFileName(file);
string[] lines = File.ReadAllLines(file);
foreach (string line in lines) {
if (statementPeriodSegments is not null) {
if (line.Contains(search))
foundLines.Add(line);
} else {
if (statementPeriodFound) {
statementPeriodSegments = line.Split(' ');
continue;
}
if (!line.Contains(statementPeriod))
continue;
statementPeriodFound = true;
}
}
if (statementPeriodSegments is null || statementPeriodSegments.Length < 4)
logger.LogInformation($"{nameof(statementPeriod)}: {statementPeriod}; wasn't found in <{fileName}>!");
else
Move(logger, dateFormat, file, checkFile, fileName, statementPeriodSegments.AsReadOnly(), foundLines);
}
internal static void Move(ILogger<Worker> logger, List<string> args) {
string checkFile;
string search = args[5];
@ -72,10 +16,75 @@ internal static partial class Helper20250126 {
string[] files = Directory.GetFiles(sourceDirectory, searchPatterns, SearchOption.AllDirectories);
foreach (string file in files) {
checkFile = Path.ChangeExtension(file, ".pdf");
if (!File.Exists(checkFile))
if (!File.Exists(checkFile)) {
continue;
}
Move(logger, file, checkFile, dateFormat, statementPeriod, search);
}
}
private static void Move(ILogger<Worker> logger, string file, string checkFile, string dateFormat, string statementPeriod, string search) {
List<string> foundLines = [];
bool statementPeriodFound = false;
string[]? statementPeriodSegments = null;
string fileName = Path.GetFileName(file);
string[] lines = File.ReadAllLines(file);
foreach (string line in lines) {
if (statementPeriodSegments is not null) {
if (line.Contains(search)) {
foundLines.Add(line);
}
} else {
if (statementPeriodFound) {
statementPeriodSegments = line.Split(' ');
continue;
}
if (!line.Contains(statementPeriod)) {
continue;
}
statementPeriodFound = true;
}
}
if (statementPeriodSegments is null || statementPeriodSegments.Length < 4) {
logger.LogInformation($"{nameof(statementPeriod)}: {statementPeriod}; wasn't found in <{fileName}>!");
} else {
Move(logger, dateFormat, file, checkFile, fileName, statementPeriodSegments.AsReadOnly(), foundLines);
}
}
private static void Move(ILogger<Worker> logger, string dateFormat, string file, string checkFile, string fileName, ReadOnlyCollection<string> statementPeriodSegments, List<string> foundLines) {
DateTime dateTime;
List<DateTime> dateTimes = [];
foreach (string check in statementPeriodSegments) {
if (!DateTime.TryParseExact(check, dateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) {
continue;
}
dateTimes.Add(dateTime);
}
if (dateTimes.Count != 2) {
logger.LogInformation($"Only {dateTimes.Count} date(s) were found in <{fileName}>!");
} else {
Move(file, fileName, checkFile, foundLines, dateTimes.AsReadOnly());
}
}
private static void Move(string file, string fileName, string checkFile, List<string> foundLines, ReadOnlyCollection<DateTime> dateTimes) {
string checkDirectory = Path.Combine(Path.GetDirectoryName(file) ?? throw new Exception(), dateTimes[0].ToString("yyyy-MM"));
if (!Directory.Exists(checkDirectory)) {
_ = Directory.CreateDirectory(checkDirectory);
}
string fileNameB = Path.GetFileName(checkFile);
string checkFileB = Path.Combine(checkDirectory, fileName);
string checkFileC = Path.Combine(checkDirectory, fileNameB);
string contents = string.Join(Environment.NewLine, foundLines);
string checkFileD = Path.Combine(checkDirectory, $"{fileName}.txt");
if (!File.Exists(checkFileB)) {
File.Move(file, checkFileB);
}
if (!File.Exists(checkFileC)) {
File.Move(checkFile, checkFileC);
}
File.WriteAllText(checkFileD, contents);
}
}

View File

@ -16,37 +16,6 @@ internal static partial class Helper20250204 {
[GeneratedRegex("[\\s!?.,@:;|\\\\/\"'`£$%\\^&*{}[\\]()<>~#+\\-=_¬]+")]
private static partial Regex InvalidCharacter();
private record H1ParamCaseAndState(string H1, string ParamCase, string State) {
private static string GetParamCase(string value) {
string result;
StringBuilder stringBuilder = new(value);
Match[] matches = UpperCase().Matches(value).ToArray();
for (int i = matches.Length - 1; i > -1; i--)
_ = stringBuilder.Insert(matches[i].Index, '-');
string[] segments = InvalidCharacter().Split(stringBuilder.ToString().ToLower());
result = string.Join('-', segments).Trim('-');
return result;
}
private static string GetState(string value) =>
value switch {
"New" => "ToDo",
"Active" => "In Progress",
"Closed" => "Done",
_ => "Backlog",
};
internal static H1ParamCaseAndState Get(WorkItem workItem) {
H1ParamCaseAndState result;
string paramCase = GetParamCase(workItem.Title);
string state = GetState(workItem.State);
result = new(workItem.Title, paramCase, state);
return result;
}
}
private record Attribute([property: JsonPropertyName("isLocked")] bool IsLocked,
[property: JsonPropertyName("name")] string Name,
[property: JsonPropertyName("parameterTitle")] string? ParameterTitle,
@ -148,16 +117,6 @@ internal static partial class Helper20250204 {
private static string GetTaskText(string directory, string rootDirectory) =>
string.Join(Environment.NewLine, GetTaskLines(directory, rootDirectory));
private static void WriteTaskFile(string sourceDirectory, string rootDirectory) {
string tasksFile = Path.Combine(sourceDirectory, ".vscode", "tasks.json");
string oldText = File.ReadAllText(tasksFile);
string jsonSafeDirectory = sourceDirectory.Replace('\\', '/');
if (!oldText.Contains(jsonSafeDirectory)) {
string text = GetTaskText(jsonSafeDirectory, rootDirectory);
File.WriteAllText(tasksFile, text);
}
}
private static string GetFilter(ReadOnlyCollection<H1ParamCaseAndState> collection, string filter) =>
string.Join(Environment.NewLine, from l in collection where l.State == filter select $"- [{l.ParamCase}](tasks/{l.ParamCase}.md)");
@ -192,6 +151,103 @@ internal static partial class Helper20250204 {
private static string GetIndexText(WorkItem workItem, H1ParamCaseAndState h1ParamCaseAndState, ReadOnlyCollection<H1ParamCaseAndState> collection) =>
string.Join(Environment.NewLine, GetIndexLines(workItem, h1ParamCaseAndState, collection));
internal static void ExtractKanban(ILogger<Worker> logger, List<string> args) {
string searchPattern = "*.json";
string fullPath = Path.GetFullPath(args[0]);
string sourceDirectory = GetSourceDirectory(fullPath);
string rootDirectory = args.Count < 3 || args[2].Length < 16 ? "D:/5-Other-Small/Kanban-mestsa003/{}" : args[2];
WriteTaskFile(sourceDirectory, rootDirectory);
string sourceDirectoryName = Path.GetFileName(sourceDirectory);
DirectoryInfo directoryInfo = new(Path.Combine(sourceDirectory, ".kanbn"));
FileInfo? fileInfo = !directoryInfo.Exists ? null : new(Path.Combine(directoryInfo.FullName, $"{sourceDirectoryName}.json"));
if (directoryInfo.Exists && fileInfo is not null && fileInfo.Exists) {
ExtractKanban(searchPattern, rootDirectory, directoryInfo, fileInfo);
} else {
logger.LogWarning("<{directoryInfo}> doesn't exist", directoryInfo.FullName);
}
}
private static string GetSourceDirectory(string directory) {
string? result = null;
DirectoryInfo directoryInfo;
string? checkDirectory = directory;
string? pathRoot = Path.GetPathRoot(directory);
for (int i = 0; i < int.MaxValue; i++) {
checkDirectory = Path.GetDirectoryName(checkDirectory);
if (string.IsNullOrEmpty(checkDirectory) || checkDirectory == pathRoot) {
break;
}
directoryInfo = new(checkDirectory);
if (string.IsNullOrEmpty(directoryInfo.LinkTarget)) {
continue;
}
result = directory.Replace(checkDirectory, directoryInfo.LinkTarget);
break;
}
result ??= directory;
return result;
}
private static void WriteTaskFile(string sourceDirectory, string rootDirectory) {
string tasksFile = Path.Combine(sourceDirectory, ".vscode", "tasks.json");
string oldText = File.ReadAllText(tasksFile);
string jsonSafeDirectory = sourceDirectory.Replace('\\', '/');
if (!oldText.Contains(jsonSafeDirectory)) {
string text = GetTaskText(jsonSafeDirectory, rootDirectory);
File.WriteAllText(tasksFile, text);
}
}
private static void ExtractKanban(string searchPattern, string rootDirectory, DirectoryInfo kanbanDirectory, FileInfo fileInfo) {
string checkFile;
string weekOfYear;
string workItemDirectory;
string line = Environment.NewLine;
H1ParamCaseAndState h1ParamCaseAndState;
Calendar calendar = new CultureInfo("en-US").Calendar;
string tasksDirectory = Path.Combine(kanbanDirectory.FullName, "tasks");
if (!Directory.Exists(tasksDirectory)) {
_ = Directory.CreateDirectory(tasksDirectory);
}
string[] files = Directory.GetFiles(tasksDirectory, searchPattern, SearchOption.TopDirectoryOnly);
ReadOnlyCollection<WorkItem> workItems = GetWorkItems(files);
string markdown = GetIndexMarkdown(fileInfo, workItems);
string indexFile = Path.Combine(kanbanDirectory.FullName, "index.md");
string markdownOld = File.Exists(indexFile) ? File.ReadAllText(indexFile) : string.Empty;
if (markdown != markdownOld) {
File.WriteAllText(indexFile, markdown);
}
foreach (WorkItem workItem in workItems) {
h1ParamCaseAndState = H1ParamCaseAndState.Get(workItem);
checkFile = Path.Combine(tasksDirectory, $"{h1ParamCaseAndState.ParamCase}.md");
markdownOld = File.Exists(checkFile) ? File.ReadAllText(checkFile) : string.Empty;
if (markdownOld.Contains("](")) {
continue;
}
weekOfYear = calendar.GetWeekOfYear(workItem.CreatedDate, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00");
workItemDirectory = Path.GetFullPath(Path.Combine(rootDirectory, $"{workItem.CreatedDate:yyyy}", $"{workItem.CreatedDate:yyyy}_Week_{weekOfYear}", $"{workItem.Id}"));
markdown = $"# {h1ParamCaseAndState.H1}{line}{line}## Id {workItem.Id}{line}{line}## Code Insiders{line}{line}- [code-insiders]({workItemDirectory}){line}";
if (markdown != markdownOld) {
File.WriteAllText(checkFile, markdown);
}
}
}
private static ReadOnlyCollection<WorkItem> GetWorkItems(string[] files) {
List<WorkItem> results = [];
string json;
WorkItem? workItem;
foreach (string file in files) {
json = File.ReadAllText(file);
workItem = JsonSerializer.Deserialize(json, WorkItemSourceGenerationContext.Default.WorkItem);
if (workItem is null) {
continue;
}
results.Add(workItem);
}
return results.AsReadOnly();
}
private static string GetIndexMarkdown(FileInfo fileInfo, ReadOnlyCollection<WorkItem> workItems) {
string result;
H1ParamCaseAndState h1ParamCaseAndState;
@ -210,83 +266,36 @@ internal static partial class Helper20250204 {
return result;
}
private static ReadOnlyCollection<WorkItem> GetWorkItems(string[] files) {
List<WorkItem> results = [];
string json;
WorkItem? workItem;
foreach (string file in files) {
json = File.ReadAllText(file);
workItem = JsonSerializer.Deserialize(json, WorkItemSourceGenerationContext.Default.WorkItem);
if (workItem is null)
continue;
results.Add(workItem);
}
return results.AsReadOnly();
}
private record H1ParamCaseAndState(string H1, string ParamCase, string State) {
private static void ExtractKanban(string searchPattern, string rootDirectory, DirectoryInfo kanbanDirectory, FileInfo fileInfo) {
string checkFile;
string weekOfYear;
string workItemDirectory;
string line = Environment.NewLine;
H1ParamCaseAndState h1ParamCaseAndState;
Calendar calendar = new CultureInfo("en-US").Calendar;
string tasksDirectory = Path.Combine(kanbanDirectory.FullName, "tasks");
if (!Directory.Exists(tasksDirectory))
_ = Directory.CreateDirectory(tasksDirectory);
string[] files = Directory.GetFiles(tasksDirectory, searchPattern, SearchOption.TopDirectoryOnly);
ReadOnlyCollection<WorkItem> workItems = GetWorkItems(files);
string markdown = GetIndexMarkdown(fileInfo, workItems);
string indexFile = Path.Combine(kanbanDirectory.FullName, "index.md");
string markdownOld = File.Exists(indexFile) ? File.ReadAllText(indexFile) : string.Empty;
if (markdown != markdownOld)
File.WriteAllText(indexFile, markdown);
foreach (WorkItem workItem in workItems) {
h1ParamCaseAndState = H1ParamCaseAndState.Get(workItem);
checkFile = Path.Combine(tasksDirectory, $"{h1ParamCaseAndState.ParamCase}.md");
markdownOld = File.Exists(checkFile) ? File.ReadAllText(checkFile) : string.Empty;
if (markdownOld.Contains("]("))
continue;
weekOfYear = calendar.GetWeekOfYear(workItem.CreatedDate, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00");
workItemDirectory = Path.GetFullPath(Path.Combine(rootDirectory, $"{workItem.CreatedDate:yyyy}", $"{workItem.CreatedDate:yyyy}_Week_{weekOfYear}", $"{workItem.Id}"));
markdown = $"# {h1ParamCaseAndState.H1}{line}{line}## Id {workItem.Id}{line}{line}## Code Insiders{line}{line}- [code-insiders]({workItemDirectory}){line}";
if (markdown != markdownOld)
File.WriteAllText(checkFile, markdown);
private static string GetParamCase(string value) {
string result;
StringBuilder stringBuilder = new(value);
Match[] matches = UpperCase().Matches(value).ToArray();
for (int i = matches.Length - 1; i > -1; i--) {
_ = stringBuilder.Insert(matches[i].Index, '-');
}
string[] segments = InvalidCharacter().Split(stringBuilder.ToString().ToLower());
result = string.Join('-', segments).Trim('-');
return result;
}
}
private static string GetSourceDirectory(string directory) {
string? result = null;
DirectoryInfo directoryInfo;
string? checkDirectory = directory;
string? pathRoot = Path.GetPathRoot(directory);
for (int i = 0; i < int.MaxValue; i++) {
checkDirectory = Path.GetDirectoryName(checkDirectory);
if (string.IsNullOrEmpty(checkDirectory) || checkDirectory == pathRoot)
break;
directoryInfo = new(checkDirectory);
if (string.IsNullOrEmpty(directoryInfo.LinkTarget))
continue;
result = directory.Replace(checkDirectory, directoryInfo.LinkTarget);
break;
private static string GetState(string value) =>
value switch {
"New" => "ToDo",
"Active" => "In Progress",
"Closed" => "Done",
_ => "Backlog",
};
internal static H1ParamCaseAndState Get(WorkItem workItem) {
H1ParamCaseAndState result;
string paramCase = GetParamCase(workItem.Title);
string state = GetState(workItem.State);
result = new(workItem.Title, paramCase, state);
return result;
}
result ??= directory;
return result;
}
internal static void ExtractKanban(ILogger<Worker> logger, List<string> args) {
string searchPattern = "*.json";
string fullPath = Path.GetFullPath(args[0]);
string sourceDirectory = GetSourceDirectory(fullPath);
string rootDirectory = args.Count < 3 || args[2].Length < 16 ? "D:/5-Other-Small/Kanban-mestsa003/{}" : args[2];
WriteTaskFile(sourceDirectory, rootDirectory);
string sourceDirectoryName = Path.GetFileName(sourceDirectory);
DirectoryInfo directoryInfo = new(Path.Combine(sourceDirectory, ".kanbn"));
FileInfo? fileInfo = !directoryInfo.Exists ? null : new(Path.Combine(directoryInfo.FullName, $"{sourceDirectoryName}.json"));
if (directoryInfo.Exists && fileInfo is not null && fileInfo.Exists)
ExtractKanban(searchPattern, rootDirectory, directoryInfo, fileInfo);
else
logger.LogWarning("<{directoryInfo}> doesn't exist", directoryInfo.FullName);
}
}