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 GetRecords(string sourceDirectory, string timestampFormat) { List 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> data, List timestamps, string timestamp, DateTime dateTime) { List 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 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 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> GetEquipmentToRecords(string sourceDirectory, string timestampFormat) { Dictionary> results = []; List? collection; Dictionary> keyValuePairs = []; ReadOnlyCollection 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> keyValuePair in keyValuePairs) results.Add(keyValuePair.Key, new(keyValuePair.Value)); return new(results); } private static void ParseProcessDataStandardFormatRecords(ILogger logger, string sourceDirectory, string timestampFormat, string keyColumn, string missingKeyDirectory, string parsedDirectory, ReadOnlyCollection records) { string[] lines; string[] values; string[] columns; DateTime dateTime; string parsedFile; int? keyColumnIndex; string keyColumnValue; string? lastColumn = null; List> data = []; List timestamps = []; List 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 logger, string sourceDirectory, string timestampFormat, string keyColumn, string missingKeyDirectory) { string parsedDirectory; ReadOnlyDictionary> equipmentToRecords = GetEquipmentToRecords(sourceDirectory, timestampFormat); foreach (KeyValuePair> 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 logger, List 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); } } }