184 lines
8.2 KiB
C#
184 lines
8.2 KiB
C#
|
|
using System.Collections.ObjectModel;
|
|
using System.Globalization;
|
|
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
using System.Text.RegularExpressions;
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace File_Folder_Helper.ADO2025.PI6;
|
|
|
|
internal static partial class Helper20250521 {
|
|
|
|
[GeneratedRegex(@"[~\-,.0-9]")]
|
|
private static partial Regex Number();
|
|
|
|
[GeneratedRegex(@"[^\u0020-\u007E]")]
|
|
private static partial Regex ASCII();
|
|
|
|
private record Record(string Directory, string FileNameWithoutExtension);
|
|
|
|
private record LineCheck(string[] Segments, DateTime TransactionDate, DateTime EffectiveDate) {
|
|
|
|
internal static LineCheck Get(int dateLineSegmentCount, string datePattern, string line) {
|
|
LineCheck result;
|
|
string[] segments = line.Split(' ');
|
|
if (segments.Length >= dateLineSegmentCount
|
|
&& segments[0].Length == datePattern.Length
|
|
&& segments[1].Length == datePattern.Length
|
|
&& DateTime.TryParseExact(segments[0], datePattern, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime transactionDate)
|
|
&& DateTime.TryParseExact(segments[1], datePattern, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime effectiveDate)) {
|
|
result = new(Segments: segments, TransactionDate: transactionDate, EffectiveDate: effectiveDate);
|
|
} else {
|
|
result = new(Segments: segments, TransactionDate: DateTime.MinValue, EffectiveDate: DateTime.MinValue);
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
|
|
private record RecordB(int I,
|
|
DateTime TransactionDate,
|
|
DateTime EffectiveDate,
|
|
string Description,
|
|
decimal WithdrawalOrDeposit,
|
|
decimal Balance);
|
|
|
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
|
[JsonSerializable(typeof(RecordB[]))]
|
|
private partial class Helper20250521RecordB : JsonSerializerContext {
|
|
}
|
|
|
|
internal static void MatchDirectory(ILogger<Worker> logger, List<string> args) {
|
|
Record record;
|
|
string datePattern = args[5];
|
|
string searchPattern = args[2];
|
|
string searchPatternB = args[3];
|
|
string columns = args[6].Replace('~', ',');
|
|
int dateLineSegmentCount = int.Parse(args[4]);
|
|
string sourceDirectory = Path.GetFullPath(args[0].Split('~')[0]);
|
|
ReadOnlyDictionary<string, string> keyValuePairs = GetKeyValuePairs(searchPattern, sourceDirectory);
|
|
MoveMatchDirectory(searchPatternB, keyValuePairs, sourceDirectory);
|
|
ReadOnlyCollection<RecordB> records = GetRecords(searchPatternB, sourceDirectory, dateLineSegmentCount, datePattern, columns);
|
|
WriteRecords(sourceDirectory, records);
|
|
}
|
|
|
|
private static ReadOnlyDictionary<string, string> GetKeyValuePairs(string searchPattern, string sourceDirectory) {
|
|
Dictionary<string, string> results = [];
|
|
string[] files = Directory.GetFiles(sourceDirectory, searchPattern, SearchOption.AllDirectories);
|
|
foreach (string file in files) {
|
|
results.Add(Path.GetFileNameWithoutExtension(file), Path.GetDirectoryName(file));
|
|
}
|
|
return results.AsReadOnly();
|
|
}
|
|
|
|
private static void MoveMatchDirectory(string searchPatternB, ReadOnlyDictionary<string, string> keyValuePairs, string sourceDirectory) {
|
|
string checkFile;
|
|
string fileNameWithoutExtension;
|
|
string[] files = Directory.GetFiles(sourceDirectory, searchPatternB, SearchOption.AllDirectories);
|
|
foreach (string file in files) {
|
|
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file);
|
|
if (!keyValuePairs.TryGetValue(fileNameWithoutExtension, out string? match))
|
|
continue;
|
|
checkFile = Path.Combine(match, Path.GetFileName(file));
|
|
if (File.Exists(checkFile))
|
|
continue;
|
|
File.Move(file, checkFile);
|
|
}
|
|
}
|
|
|
|
private static ReadOnlyCollection<RecordB> GetRecords(string searchPatternB, string sourceDirectory, int dateLineSegmentCount, string datePattern, string columns) {
|
|
List<RecordB> results = [];
|
|
string line;
|
|
string[] lines;
|
|
RecordB? record;
|
|
LineCheck lineCheck;
|
|
string[] files = Directory.GetFiles(sourceDirectory, searchPatternB, SearchOption.AllDirectories);
|
|
foreach (string file in files) {
|
|
lines = File.ReadAllLines(file);
|
|
for (int i = 0; i < lines.Length; i++) {
|
|
line = lines[i];
|
|
if (string.IsNullOrEmpty(line)) {
|
|
continue;
|
|
}
|
|
lineCheck = LineCheck.Get(dateLineSegmentCount, datePattern, line);
|
|
if (lineCheck.EffectiveDate == DateTime.MinValue || lineCheck.TransactionDate == DateTime.MinValue) {
|
|
continue;
|
|
} else {
|
|
record = GetRecord(dateLineSegmentCount, datePattern, lines, i, lineCheck.Segments, lineCheck.TransactionDate, lineCheck.EffectiveDate);
|
|
if (record is not null) {
|
|
i = record.I;
|
|
results.Add(record);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return results.AsReadOnly();
|
|
}
|
|
|
|
private static RecordB? GetRecord(int dateLineSegmentCount, string datePattern, string[] lines, int i, string[] segments, DateTime transactionDate, DateTime effectiveDate) {
|
|
RecordB? result = null;
|
|
string line;
|
|
RecordB record;
|
|
LineCheck lineCheck;
|
|
List<string> collection = [];
|
|
for (int j = i + 1; j < lines.Length; j++) {
|
|
line = lines[j];
|
|
if (string.IsNullOrEmpty(line)) {
|
|
continue;
|
|
}
|
|
lineCheck = LineCheck.Get(dateLineSegmentCount, datePattern, line);
|
|
if (lineCheck.EffectiveDate == DateTime.MinValue || lineCheck.TransactionDate == DateTime.MinValue) {
|
|
collection.Add(line);
|
|
} else {
|
|
if (lineCheck.Segments.Length > dateLineSegmentCount) {
|
|
collection.Insert(0, string.Join(' ', lineCheck.Segments.Skip(2)));
|
|
}
|
|
result = GetRecord(transactionDate, effectiveDate, collection.AsReadOnly(), j - 1);
|
|
break;
|
|
}
|
|
}
|
|
if (result is null && collection.Count > 0) {
|
|
result = GetRecord(transactionDate, effectiveDate, collection.AsReadOnly(), lines.Length - 1);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private static RecordB GetRecord(DateTime transactionDate, DateTime effectiveDate, ReadOnlyCollection<string> collection, int i) {
|
|
RecordB? result;
|
|
List<string> verified = [];
|
|
foreach (string check in collection) {
|
|
if (Number().Replace(check, string.Empty).Length != 0) {
|
|
verified.Clear();
|
|
} else {
|
|
verified.Add(check);
|
|
}
|
|
if (verified.Count == 2) {
|
|
break;
|
|
}
|
|
}
|
|
if (verified.Count != 2) {
|
|
result = null;
|
|
} else {
|
|
decimal balance = decimal.Parse(verified[^1]);
|
|
decimal withdrawalOrDeposit = decimal.Parse(verified[^2]);
|
|
string description = ASCII().Replace(string.Join(' ', collection.SkipLast(2)), string.Empty);
|
|
result = new(I: i,
|
|
TransactionDate: transactionDate,
|
|
EffectiveDate: effectiveDate,
|
|
Description: description,
|
|
WithdrawalOrDeposit: withdrawalOrDeposit,
|
|
Balance: balance);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private static void WriteRecords(string sourceDirectory, ReadOnlyCollection<RecordB> records) {
|
|
string json = JsonSerializer.Serialize(records.ToArray(), Helper20250521RecordB.Default.RecordBArray);
|
|
string sourceDirectoryVsCode = Path.Combine(sourceDirectory, ".vscode");
|
|
if (!Directory.Exists(sourceDirectoryVsCode))
|
|
_ = Directory.CreateDirectory(sourceDirectoryVsCode);
|
|
File.WriteAllText(Path.Combine(sourceDirectoryVsCode, $"{DateTime.Now.Ticks}.json"), json);
|
|
}
|
|
|
|
} |