using Microsoft.Extensions.Logging; using System.Collections.ObjectModel; using System.Globalization; using System.Text.Json; using System.Text.Json.Serialization; using System.Text.RegularExpressions; namespace File_Folder_Helper.ADO2024.PI3; internal static partial class Helper20240828 { private record HeaderCommon(DateTime Date, string? Employee, string? Layer, string? MesEntity, string? PSN, string? Quantity, string? RDS, string? Reactor, string? Recipe, string? Zone); [JsonSourceGenerationOptions(WriteIndented = true)] [JsonSerializable(typeof(HeaderCommon))] private partial class HeaderCommonSourceGenerationContext : JsonSerializerContext { } private record Record(string? CassetteId, ReadOnlyCollection? CassetteSegments, DateTime? Date, string? Employee, ReadOnlyCollection? EquipmentSegments, int I, string? LastDate, ReadOnlyCollection>? Matches); private static Record GetRecord(int i, string? lastDate, ReadOnlyCollection> matches) { Record result; if (matches.Count != 4 || matches[0].Count != 3 || matches[3].Count != 3) result = new Record(null, null, null, null, null, i, null, null); else { string[] equipmentSegments = matches[1][2].Split('|'); if (equipmentSegments.Length != 2) result = new Record(null, null, null, null, null, i, null, null); else { string[] cassetteIdSegments = matches[3][2].Split('|'); if (cassetteIdSegments.Length <= 3) result = new Record(null, null, null, null, null, i, null, null); else { string cassetteId = Regex.Replace(cassetteIdSegments[2], @"[\\,\/,\:,\*,\?,\"",\<,\>,\|]", "_").Split('\r')[0].Split('\n')[0]; result = new Record(cassetteId, new(cassetteIdSegments), DateTime.Parse(matches[0][0]), matches[0][1], new(equipmentSegments), i, lastDate, new(matches)); } } } return result; } private static ReadOnlyCollection GetRecords(string logDirectory, string logSearchPattern) { List results = []; Record record; string[] lines; string[] logFiles = Directory.GetFiles(logDirectory, logSearchPattern, SearchOption.TopDirectoryOnly); if (logFiles.Length > 0) { } foreach (string logFile in new List()) // logFiles) { lines = File.ReadAllLines(logFile); for (int i = lines.Length - 1; i >= 0; i--) { record = GetRecord(lines, i); i = record.I; if (record.CassetteId is null || record.CassetteSegments is null || record.Date is null || record.Employee is null || record.EquipmentSegments is null || record.Matches is null) { if (i < 4) break; continue; } results.Add(record); } } return new(results); } private static Dictionary> GetKeyValuePairs(Dictionary> keyValuePairs) { Dictionary> results = []; foreach (KeyValuePair> keyValuePair in keyValuePairs) results.Add(keyValuePair.Key, new(keyValuePair.Value)); return new(results); } private static Record GetRecord(string[] lines, int i) { Record result; int ii = i; string line; string[] segments; string? lastDate = null; List> matches = []; for (int j = i; j >= 0; j--) { ii = j; line = lines[j]; segments = line.Split(','); if (segments.Length < 2) continue; lastDate ??= segments[0]; if (segments[0] != lastDate) { lastDate = segments[0]; break; } matches.Add(new(segments)); } result = GetRecord(ii + 1, lastDate, new(matches)); return result; } private static Dictionary> GetKeyValuePairs(string logSearchPattern, string logDirectory) { Dictionary> results; int totalMinutes; TimeSpan timeSpan; List? collection; Dictionary> keyValuePairs = []; ReadOnlyCollection records = GetRecords(logDirectory, logSearchPattern); foreach (Record record in records) { if (record.CassetteId is null || record.CassetteSegments is null || record.Date is null || record.Employee is null || record.EquipmentSegments is null || record.Matches is null) continue; timeSpan = TimeSpan.FromTicks(record.Date.Value.Ticks); totalMinutes = (int)Math.Floor(timeSpan.TotalMinutes); if (!keyValuePairs.TryGetValue(totalMinutes, out collection)) { keyValuePairs.Add(totalMinutes, []); if (!keyValuePairs.TryGetValue(totalMinutes, out collection)) throw new Exception(); } collection.Add(record); } results = GetKeyValuePairs(keyValuePairs); return results; } internal static void MoveWaferCounterToArchive(ILogger logger, List args) { string json; string keyFile; string? recipe; string[] lines; string checkFile; string directory; string? quantity; string runDataSheet; string checkDirectory; HeaderCommon headerCommon; string logDateFormat = args[3]; string wcSearchPattern = args[5]; string logSearchPattern = $"SKIP---{args[2]}"; string logDirectory = Path.GetFullPath(args[0]); string sourceDirectory = Path.GetFullPath(args[4]); string archiveDirectory = Path.GetFullPath(args[6]); FileInfo[] collection = Directory.GetFiles(sourceDirectory, wcSearchPattern, SearchOption.AllDirectories).Select(l => new FileInfo(l)).ToArray(); logger.LogInformation("Found {collection}(s)", collection.Length); foreach (FileInfo fileInfo in collection) { if (fileInfo.DirectoryName is null || !fileInfo.DirectoryName.Contains('-')) continue; lines = File.ReadAllLines(fileInfo.FullName); recipe = lines.Length < 2 ? null : lines[1]; quantity = lines.Length < 1 ? null : lines[0]; keyFile = $"{fileInfo.FullName}.txt"; if (!File.Exists(keyFile)) continue; lines = File.ReadAllLines(keyFile); if (lines.Length != 1) continue; runDataSheet = Regex.Replace(lines[0], @"[\\,\/,\:,\*,\?,\"",\<,\>,\|]", ".").Split('\r')[0].Split('\n')[0]; directory = Path.Combine(fileInfo.DirectoryName, runDataSheet); checkDirectory = Path.Combine(directory, fileInfo.LastWriteTime.Ticks.ToString()); if (!Directory.Exists(checkDirectory)) _ = Directory.CreateDirectory(checkDirectory); checkFile = Path.Combine(directory, fileInfo.Name); if (File.Exists(checkFile)) continue; headerCommon = new(fileInfo.LastWriteTime, null, null, null, null, quantity, runDataSheet, null, recipe, null); json = JsonSerializer.Serialize(headerCommon, HeaderCommonSourceGenerationContext.Default.HeaderCommon); File.Move(fileInfo.FullName, checkFile); File.Delete(keyFile); checkFile = Path.Combine(checkDirectory, $"{fileInfo.Name}.json"); if (File.Exists(checkFile)) continue; File.WriteAllText(checkFile, json); Directory.SetLastWriteTime(checkDirectory, fileInfo.LastWriteTime); } Record record; int totalMinutes; string weekOfYear; TimeSpan timeSpan; ReadOnlyCollection? records; Calendar calendar = new CultureInfo("en-US").Calendar; Dictionary> keyValuePairs = GetKeyValuePairs(logSearchPattern, logDirectory); logger.LogInformation("Mapped {keyValuePairs}(s)", keyValuePairs.Count); foreach (FileInfo fileInfo in collection) { if (fileInfo.DirectoryName is null || fileInfo.DirectoryName.Contains('-')) continue; timeSpan = TimeSpan.FromTicks(fileInfo.LastWriteTime.Ticks); totalMinutes = (int)Math.Floor(timeSpan.TotalMinutes); if (!keyValuePairs.TryGetValue(totalMinutes, out records)) continue; if (records.Count != 1) continue; record = records[0]; if (record.CassetteId is null || record.CassetteSegments is null || record.Date is null || record.Employee is null || record.EquipmentSegments is null || record.Matches is null) continue; weekOfYear = $"{record.Date.Value.Year}_Week_{calendar.GetWeekOfYear(record.Date.Value, CalendarWeekRule.FirstDay, DayOfWeek.Sunday):00}"; checkDirectory = Path.Combine(archiveDirectory, string.Join('-', record.EquipmentSegments.Reverse()), weekOfYear, record.Date.Value.ToString("yyyy-MM-dd"), record.CassetteId); if (!Directory.Exists(checkDirectory)) _ = Directory.CreateDirectory(checkDirectory); checkFile = Path.Combine(checkDirectory, fileInfo.Name); if (File.Exists(checkFile)) continue; File.Move(fileInfo.FullName, checkFile); lines = record.Matches.Select(l => string.Join(',', l)).ToArray(); File.WriteAllLines($"{checkFile}.txt", lines); } } }