file-folder-helper/Day/2023-Q4/Helper-2023-11-22.cs
Mike Phares 84ad97ac6e SortCodeMethods
DirectoryToISO
TextToJson
2024-01-08 10:02:30 -07:00

195 lines
8.6 KiB
C#

using Microsoft.Extensions.Logging;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IO.Compression;
namespace File_Folder_Helper.Day;
internal static class Helper20231122
{
private record Record(string File, string FileName, string Equipment, string TimeStamp);
private static ReadOnlyCollection<Record> GetRecords(string sourceDirectory, string timestampFormat)
{
List<Record> results = [];
Record record;
string fileName;
string equipment;
string timestamp;
string[] segments;
string[] files = Directory.GetFiles(sourceDirectory, "*.pdsf", SearchOption.TopDirectoryOnly).ToArray();
foreach (string file in files)
{
fileName = Path.GetFileName(file);
segments = fileName.Split('_');
if (segments.Length != 2)
continue;
equipment = segments[0];
timestamp = segments[1].Split('.')[0];
if (timestamp.Length != timestampFormat.Length)
continue;
record = new(file, fileName, equipment, timestamp);
results.Add(record);
}
return new(results.OrderBy(l => l.TimeStamp).ToArray());
}
private static void WriteFile(string sourceDirectory, string[] columns, string equipment, List<List<string>> data, List<string> timestamps, string timestamp, DateTime dateTime)
{
List<string> lines = [];
string checkFile = Path.Combine(sourceDirectory, $"{equipment}-{timestamp}.tvs");
if (File.Exists(checkFile))
throw new NotSupportedException();
lines.Add($"timestamp\t{string.Join('\t', timestamps)}");
for (int i = 0; i < columns.Length; i++)
lines.Add($"{columns[i]}\t{string.Join('\t', data[i])}");
File.WriteAllLines(checkFile, lines);
File.SetLastWriteTime(checkFile, dateTime);
}
private static void ZipAndDeleteFiles(string sourceDirectory, string equipment, string timestamp, List<string> files, DateTime dateTime)
{
string checkFile = Path.Combine(sourceDirectory, $"{equipment}-{timestamp}.zip");
if (File.Exists(checkFile))
throw new NotSupportedException();
using ZipArchive zip = ZipFile.Open(checkFile, ZipArchiveMode.Create);
foreach (string file in files)
{
_ = zip.CreateEntryFromFile(file, Path.GetFileName(file));
File.Delete(file);
}
File.SetLastWriteTime(checkFile, dateTime);
}
private static void MoveFilesBack(string sourceDirectory, string parsedDirectory, List<string> parsedFiles)
{
foreach (string parsedFile in parsedFiles)
File.Move(parsedFile, Path.Combine(sourceDirectory, Path.GetFileName(parsedFile)));
if (parsedFiles.Count > 0)
Directory.Delete(parsedDirectory);
}
private static ReadOnlyDictionary<string, ReadOnlyCollection<Record>> GetEquipmentToRecords(string sourceDirectory, string timestampFormat)
{
Dictionary<string, ReadOnlyCollection<Record>> results = [];
List<Record>? collection;
Dictionary<string, List<Record>> keyValuePairs = [];
ReadOnlyCollection<Record> records = GetRecords(sourceDirectory, timestampFormat);
foreach (Record record in records)
{
if (!keyValuePairs.TryGetValue(record.Equipment, out collection))
{
keyValuePairs.Add(record.Equipment, []);
if (!keyValuePairs.TryGetValue(record.Equipment, out collection))
throw new NotSupportedException();
}
collection.Add(record);
}
foreach (KeyValuePair<string, List<Record>> keyValuePair in keyValuePairs)
results.Add(keyValuePair.Key, new(keyValuePair.Value));
return new(results);
}
private static void ParseProcessDataStandardFormatRecords(ILogger<Worker> logger, string sourceDirectory, string timestampFormat, string keyColumn, string missingKeyDirectory, string parsedDirectory, ReadOnlyCollection<Record> records)
{
string[] lines;
string[] values;
string[] columns;
DateTime dateTime;
string parsedFile;
int? keyColumnIndex;
string keyColumnValue;
string? lastColumn = null;
List<List<string>> data = [];
List<string> timestamps = [];
List<string> parsedFiles = [];
int? lastKeyColumnIndex = null;
string? lastKeyColumnValue = null;
foreach (Record record in records)
{
lines = File.ReadAllLines(record.File);
if (lines.Length != 15)
continue;
if (lines[6].Length < 1 || lines[6][0] != '"' || !lines[6].StartsWith("\"Time\""))
continue;
if (lines[8].Length < 1 || lines[8][0] != 'N' || lines[8] != "NUM_DATA_ROWS\t000000001")
continue;
keyColumnIndex = null;
columns = lines[6].Split('\t');
if (columns.Length < 3)
continue;
values = lines[7].Split('\t');
if (values.Length != columns.Length)
continue;
for (int i = 0; i < columns.Length; i++)
{
if (columns[i] != keyColumn)
continue;
keyColumnIndex = i;
break;
}
if (keyColumnIndex is null)
{
File.Move(record.File, Path.Combine(sourceDirectory, missingKeyDirectory, record.FileName));
continue;
}
keyColumnValue = values[keyColumnIndex.Value];
parsedFile = Path.Combine(parsedDirectory, record.FileName);
if ((lastColumn is not null && lines[6] != lastColumn) || (lastKeyColumnIndex is not null && keyColumnIndex.Value != lastKeyColumnIndex.Value) || (lastKeyColumnValue is not null && lastKeyColumnValue != keyColumnValue) || timestamps.Count > 12345)
{
if (!DateTime.TryParseExact(record.TimeStamp, timestampFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
throw new NotSupportedException();
WriteFile(sourceDirectory, columns, record.Equipment, data, timestamps, record.TimeStamp, dateTime);
ZipAndDeleteFiles(sourceDirectory, record.Equipment, record.TimeStamp, parsedFiles, dateTime);
Directory.Delete(parsedDirectory);
logger.LogInformation("{timestamp} triggered", record.TimeStamp);
parsedFiles.Clear();
break;
}
parsedFiles.Add(parsedFile);
File.Move(record.File, parsedFile);
timestamps.Add($"'{record.TimeStamp}");
for (int i = 0; i < columns.Length; i++)
data.Add([]);
for (int i = 0; i < columns.Length; i++)
data[i].Add(values[i]);
lastColumn = lines[6];
lastKeyColumnIndex = keyColumnIndex;
lastKeyColumnValue = keyColumnValue;
}
MoveFilesBack(sourceDirectory, parsedDirectory, parsedFiles);
}
private static void ParseProcessDataStandardFormatFiles(ILogger<Worker> logger, string sourceDirectory, string timestampFormat, string keyColumn, string missingKeyDirectory)
{
string parsedDirectory;
ReadOnlyDictionary<string, ReadOnlyCollection<Record>> equipmentToRecords = GetEquipmentToRecords(sourceDirectory, timestampFormat);
foreach (KeyValuePair<string, ReadOnlyCollection<Record>> keyValuePair in equipmentToRecords)
{
parsedDirectory = Path.Combine(sourceDirectory, DateTime.Now.Ticks.ToString());
if (!Directory.Exists(parsedDirectory))
_ = Directory.CreateDirectory(parsedDirectory);
ParseProcessDataStandardFormatRecords(logger, sourceDirectory, timestampFormat, keyColumn, missingKeyDirectory, parsedDirectory, keyValuePair.Value);
Thread.Sleep(100);
}
}
internal static void ProcessDataStandardFormat(ILogger<Worker> logger, List<string> args)
{
string keyColumn = args[3];
string sourceDirectory = args[0];
string timestampFormat = args[2];
if (!Directory.Exists(sourceDirectory))
throw new Exception(sourceDirectory);
string missingKeyDirectory = Path.Combine(sourceDirectory, "Missing-Key");
if (!Directory.Exists(missingKeyDirectory))
_ = Directory.CreateDirectory(missingKeyDirectory);
while (true)
{
ParseProcessDataStandardFormatFiles(logger, sourceDirectory, timestampFormat, keyColumn, missingKeyDirectory);
Thread.Sleep(5000);
}
}
}