diff --git a/Adaptation/.editorconfig b/Adaptation/.editorconfig index d117dc5..b02c0bc 100644 --- a/Adaptation/.editorconfig +++ b/Adaptation/.editorconfig @@ -109,7 +109,7 @@ dotnet_diagnostic.CA2254.severity = none # CA2254: The logging message template dotnet_diagnostic.IDE0001.severity = warning # IDE0001: Simplify name dotnet_diagnostic.IDE0002.severity = warning # Simplify (member access) - System.Version.Equals("1", "2"); Version.Equals("1", "2"); dotnet_diagnostic.IDE0004.severity = warning # IDE0004: Cast is redundant. -dotnet_diagnostic.IDE0005.severity = warning # Using directive is unnecessary +dotnet_diagnostic.IDE0005.severity = none # Using directive is unnecessary dotnet_diagnostic.IDE0028.severity = none # IDE0028: Collection initialization can be simplified dotnet_diagnostic.IDE0031.severity = warning # Use null propagation (IDE0031) dotnet_diagnostic.IDE0047.severity = warning # IDE0047: Parentheses can be removed @@ -121,6 +121,7 @@ dotnet_diagnostic.IDE0290.severity = none # Use primary constructor [Distance]cs dotnet_diagnostic.IDE0300.severity = none # IDE0300: Collection initialization can be simplified dotnet_diagnostic.IDE0301.severity = none #IDE0301: Collection initialization can be simplified dotnet_diagnostic.IDE0305.severity = none # IDE0305: Collection initialization can be simplified +dotnet_diagnostic.MSTEST0015.severity = none # MSTEST0015: Test method {method} should not be ignored dotnet_diagnostic.MSTEST0037.severity = error # MSTEST0037: Use proper 'Assert' methods dotnet_diagnostic.SYSLIB1045.severity = none # SYSLIB1045: diagnostics for regex source generation dotnet_naming_rule.abstract_method_should_be_pascal_case.severity = warning diff --git a/Adaptation/.vscode/tasks.json b/Adaptation/.vscode/tasks.json index 11ce68d..8ddfbb3 100644 --- a/Adaptation/.vscode/tasks.json +++ b/Adaptation/.vscode/tasks.json @@ -1,19 +1,134 @@ { "version": "2.0.0", + "inputs": [ + { + "default": "Development", + "description": "Which ASP Net Core Environment?", + "id": "ASPNETCORE_ENVIRONMENT", + "options": [ + "Development", + "Production" + ], + "type": "pickString" + }, + { + "default": "{AssemblyTitle}", + "description": "What Assembly Title?", + "id": "AssemblyTitle", + "type": "promptString" + }, + { + "default": "{Build.BuildId}", + "description": "Which Build BuildId?", + "id": "Build.BuildId", + "type": "promptString" + }, + { + "default": "{Build.Reason}", + "description": "Which Build Reason?", + "id": "Build.Reason", + "type": "promptString" + }, + { + "default": "{Build.Repository.Id}", + "description": "Which Build Repository Id?", + "id": "Build.Repository.Id", + "type": "promptString" + }, + { + "default": "{Build.Repository.Name}", + "description": "Which Build Repository Name?", + "id": "Build.Repository.Name", + "type": "promptString" + }, + { + "default": "{Build.SourceVersion}", + "description": "Which Build Source Version?", + "id": "Build.SourceVersion", + "type": "promptString" + }, + { + "default": "Debug", + "description": "Which Configuration?", + "id": "Configuration", + "options": [ + "Debug", + "Release" + ], + "type": "pickString" + }, + { + "default": "net8.0", + "description": "Which Core Version?", + "id": "CoreVersion", + "options": [ + "net8.0" + ], + "type": "pickString" + }, + { + "default": "C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/MSBuild/Current/Bin/MSBuild.exe", + "description": "Which MS Build?", + "id": "MSBuild", + "type": "promptString" + }, + { + "default": "https://artifactory.intra.infineon.com/artifactory/api/nuget/ngt-fi-package-main-vir/", + "description": "Which Nuget Source?", + "id": "NugetSource", + "type": "promptString" + }, + { + "default": "win-x64", + "description": "Which Runtime?", + "id": "Runtime", + "options": [ + "win-x64", + "win-x32", + "linux-x64", + "linux-x32" + ], + "type": "pickString" + }, + { + "default": "L:/", + "description": "Which System DefaultWorkingDirectory?", + "id": "System.DefaultWorkingDirectory", + "options": [ + "L:/", + "D:/", + "C:/" + ], + "type": "pickString" + }, + { + "default": "v4.8", + "description": "Which Core Target Framework Version?", + "id": "TargetFrameworkVersion", + "options": [ + "v4.8" + ], + "type": "pickString" + }, + { + "default": "{UserSecretsId}", + "description": "Which Core User Secrets Id?", + "id": "UserSecretsId", + "type": "promptString" + } + ], "tasks": [ { "label": "Build", "command": "dotnet", "type": "process", "args": [ - "build", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" + "build" ], "problemMatcher": "$msCompile" }, { - "label": "Test-Debug", + "label": "Test Debug", "command": "dotnet", "type": "process", "args": [ @@ -24,7 +139,7 @@ "problemMatcher": "$msCompile" }, { - "label": "Test-Release", + "label": "Test Release", "command": "dotnet", "type": "process", "args": [ @@ -50,7 +165,7 @@ "problemMatcher": "$msCompile" }, { - "label": "Format-Whitespaces", + "label": "Format Whitespaces", "command": "dotnet", "type": "process", "args": [ @@ -87,13 +202,13 @@ "problemMatcher": "$msCompile" }, { - "label": "Project", + "label": "Code Project", "type": "shell", "command": "code ../DEP08CEPIEPSILON.csproj", "problemMatcher": [] }, { - "label": "Readme", + "label": "Code Read Me", "type": "shell", "command": "code ../README.md", "problemMatcher": [] @@ -113,7 +228,7 @@ "problemMatcher": [] }, { - "label": "Git Config", + "label": "Code Git Config", "type": "shell", "command": "code ../.git/config", "problemMatcher": [] diff --git a/Adaptation/FileHandlers/CellInstanceConnectionName.cs b/Adaptation/FileHandlers/CellInstanceConnectionName.cs index 65ca49a..9e92df0 100644 --- a/Adaptation/FileHandlers/CellInstanceConnectionName.cs +++ b/Adaptation/FileHandlers/CellInstanceConnectionName.cs @@ -20,7 +20,9 @@ public class CellInstanceConnectionName nameof(R30) => new R30.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null), nameof(R32) => new R32.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null), nameof(R36) => new R36.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null), + nameof(R43) => new R43.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null), nameof(R55) => new R55.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null), + nameof(R56) => new R56.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null), nameof(R57) => new R57.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null), nameof(R61) => new R61.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null), nameof(R62) => new R62.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null), diff --git a/Adaptation/FileHandlers/InfinityQS/FileRead.cs b/Adaptation/FileHandlers/InfinityQS/FileRead.cs index 3a06292..c58e87c 100644 --- a/Adaptation/FileHandlers/InfinityQS/FileRead.cs +++ b/Adaptation/FileHandlers/InfinityQS/FileRead.cs @@ -5,7 +5,7 @@ using Adaptation.Shared.Duplicator; using Adaptation.Shared.Methods; using System; using System.Collections.Generic; -using System.Collections.ObjectModel; +using System.Globalization; using System.IO; using System.Linq; using System.Text.Json; @@ -15,7 +15,7 @@ namespace Adaptation.FileHandlers.InfinityQS; public class FileRead : Shared.FileRead, IFileRead { - private readonly ReadOnlyDictionary _SystemStateToNames; + private readonly int _IQSVP12Count; public FileRead(ISMTP smtp, Dictionary fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList modelObjectParameters, string equipmentDictionaryName, Dictionary> dummyRuns, Dictionary> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) : base(new Description(), false, smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null) @@ -29,17 +29,7 @@ public class FileRead : Shared.FileRead, IFileRead throw new Exception(cellInstanceConnectionName); if (!_IsDuplicator) throw new Exception(cellInstanceConnectionName); - string[] segments; - Dictionary systemStateToNames = new(); - ModelObjectParameterDefinition[] systemStates = GetProperties(cellInstanceConnectionName, modelObjectParameters, "ProcessDataStandardFormat.SystemState"); - foreach (ModelObjectParameterDefinition modelObjectParameterDefinition in systemStates) - { - segments = modelObjectParameterDefinition.Value.Split('|'); - if (segments.Length != 2) - continue; - systemStateToNames.Add(segments[0], segments[1]); - } - _SystemStateToNames = new(systemStateToNames); + _IQSVP12Count = int.Parse(GetPropertyValue(cellInstanceConnectionName, modelObjectParameters, "IQS.VP12.Count")); } void IFileRead.Move(Tuple> extractResults, Exception exception) @@ -117,50 +107,39 @@ public class FileRead : Shared.FileRead, IFileRead return results; } - private static int? GetKeyColumnIndex(string[] columns, string keyColumn) + private void CopyAndMoveFile(JsonElement[] jsonElements) { -#nullable enable - int? result = null; - for (int i = 0; i < columns.Length; i++) + string day = $"{_Logistics.DateTimeFromSequence:yyyy-MM-dd}"; + string segment = _Logistics.FileInfo.Name.Split('-')[0].Split('_')[0]; + string weekOfYear = _Calendar.GetWeekOfYear(_Logistics.DateTimeFromSequence, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00"); + string weekDirectory = $"{_Logistics.DateTimeFromSequence:yyyy}_Week_{weekOfYear}"; + string destinationDirectory = Path.Combine(_FileConnectorConfiguration.TargetFileLocation, weekDirectory, day, segment); + if (!Directory.Exists(destinationDirectory)) + _ = Directory.CreateDirectory(destinationDirectory); + string checkFile = Path.Combine(destinationDirectory, _Logistics.FileInfo.Name); + if (File.Exists(checkFile)) + File.Delete(checkFile); + File.Copy(_Logistics.FileInfo.FullName, checkFile); + if (jsonElements.Length != 1 || jsonElements[0].ValueKind != JsonValueKind.Object) + File.Delete(_Logistics.FileInfo.FullName); + else { - if (columns[i] != keyColumn) - continue; - result = i; - break; + try + { + Six six = JsonSerializer.Deserialize(jsonElements[0].GetRawText(), SixSourceGenerationContext.Default.Six) ?? throw new Exception($"{nameof(Six)} deserialization failed"); + if (six.VP12Count < _IQSVP12Count) + File.Delete(_Logistics.FileInfo.FullName); + else + { + string duplicateDirectory = Path.Combine(_FileConnectorConfiguration.SourceFileLocation, _CellInstanceName); + if (!Directory.Exists(duplicateDirectory)) + _ = Directory.CreateDirectory(duplicateDirectory); + string duplicateFile = Path.Combine(duplicateDirectory, _Logistics.FileInfo.Name); + File.Move(_Logistics.FileInfo.FullName, duplicateFile); + } + } + catch (Exception) { File.Delete(_Logistics.FileInfo.FullName); } } - return result; - } - - private ReadOnlyCollection GetSystemStateValues(List lines, string[] columns, int keyColumnIndex) - { - List results = new(); - string[] values; - string? systemState; - string keyColumnValue; - for (int i = 7; i < lines.Count; i++) - { - values = lines[i].Split('\t'); - if (values.Length != columns.Length) - continue; - keyColumnValue = values[keyColumnIndex]; - if (string.IsNullOrEmpty(keyColumnValue)) - continue; - if (!_SystemStateToNames.TryGetValue(keyColumnValue, out systemState)) - continue; - if (results.Contains(systemState)) - continue; - results.Add(systemState); - } - return new(results); - } - - private void CopyFile(string reportFullPath) - { - string duplicateDirectory = Path.Combine(_FileConnectorConfiguration.SourceFileLocation, _CellInstanceName); - if (!Directory.Exists(duplicateDirectory)) - _ = Directory.CreateDirectory(duplicateDirectory); - string duplicateFile = Path.Combine(duplicateDirectory, Path.GetFileName(reportFullPath)); - File.Copy(reportFullPath, duplicateFile, overwrite: true); } private Tuple> GetExtractResult(string reportFullPath, DateTime _) @@ -173,7 +152,7 @@ public class FileRead : Shared.FileRead, IFileRead List descriptions = GetDuplicatorDescriptions(jsonElements); Test[] tests = (from l in descriptions select (Test)l.Test).ToArray(); if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0) - CopyFile(reportFullPath); + CopyAndMoveFile(jsonElements); results = new Tuple>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics), tests, jsonElements, new List()); return results; } diff --git a/Adaptation/FileHandlers/InfinityQS/Six.cs b/Adaptation/FileHandlers/InfinityQS/Six.cs new file mode 100644 index 0000000..ea489cb --- /dev/null +++ b/Adaptation/FileHandlers/InfinityQS/Six.cs @@ -0,0 +1,41 @@ +using System.Text.Json.Serialization; + +namespace Adaptation.FileHandlers.InfinityQS; + +#nullable enable + +internal class Six +{ + + [JsonConstructor] + public Six( + string id153, + string id176, + string id221, + string id222, + string id223, + int vp12Count + ) + { + ID153 = id153; + ID176 = id176; + ID221 = id221; + ID222 = id222; + ID223 = id223; + VP12Count = vp12Count; + } + + [JsonPropertyName("id153")] public string ID153 { get; } + [JsonPropertyName("id176")] public string ID176 { get; } + [JsonPropertyName("id221")] public string ID221 { get; } + [JsonPropertyName("id222")] public string ID222 { get; } + [JsonPropertyName("id223")] public string ID223 { get; } + [JsonPropertyName("vp12_count")] public int VP12Count { get; } + +} + +[JsonSourceGenerationOptions(WriteIndented = true, NumberHandling = JsonNumberHandling.AllowReadingFromString)] +[JsonSerializable(typeof(Six))] +internal partial class SixSourceGenerationContext : JsonSerializerContext +{ +} \ No newline at end of file diff --git a/Adaptation/FileHandlers/R43/FileRead.cs b/Adaptation/FileHandlers/R43/FileRead.cs new file mode 100644 index 0000000..b21cbbb --- /dev/null +++ b/Adaptation/FileHandlers/R43/FileRead.cs @@ -0,0 +1,238 @@ +using Adaptation.Eaf.Management.ConfigurationData.CellAutomation; +using Adaptation.Ifx.Eaf.EquipmentConnector.File.Configuration; +using Adaptation.Shared; +using Adaptation.Shared.Duplicator; +using Adaptation.Shared.Methods; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text.Json; + +namespace Adaptation.FileHandlers.R43; + +public class FileRead : Shared.FileRead, IFileRead +{ + + private readonly string _KeyColumn; + private readonly string _TimestampFormat; + private readonly ReadOnlyDictionary _SystemStateToNames; + + public FileRead(ISMTP smtp, Dictionary fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList modelObjectParameters, string equipmentDictionaryName, Dictionary> dummyRuns, Dictionary> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) : + base(new Description(), false, smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null) + { + _MinFileLength = 10; + _NullData = string.Empty; + _Logistics = new(this); + if (_FileParameter is null) + throw new Exception(cellInstanceConnectionName); + if (_ModelObjectParameterDefinitions is null) + throw new Exception(cellInstanceConnectionName); + if (!_IsDuplicator) + throw new Exception(cellInstanceConnectionName); + string[] segments; + Dictionary systemStateToNames = new(); + _KeyColumn = GetPropertyValue(cellInstanceConnectionName, modelObjectParameters, "ProcessDataStandardFormat.KeyColumn"); + _TimestampFormat = GetPropertyValue(cellInstanceConnectionName, modelObjectParameters, "ProcessDataStandardFormat.TimestampFormat"); + ModelObjectParameterDefinition[] systemStates = GetProperties(cellInstanceConnectionName, modelObjectParameters, "ProcessDataStandardFormat.SystemState"); + foreach (ModelObjectParameterDefinition modelObjectParameterDefinition in systemStates) + { + segments = modelObjectParameterDefinition.Value.Split('|'); + if (segments.Length != 2) + continue; + systemStateToNames.Add(segments[0], segments[1]); + } + _SystemStateToNames = new(systemStateToNames); + } + + void IFileRead.Move(Tuple> extractResults, Exception exception) + { + bool isErrorFile = exception is not null; + if (!isErrorFile && !string.IsNullOrEmpty(_Logistics.ReportFullPath)) + { + FileInfo fileInfo = new(_Logistics.ReportFullPath); + if (fileInfo.Exists && fileInfo.LastWriteTime < fileInfo.CreationTime) + File.SetLastWriteTime(_Logistics.ReportFullPath, fileInfo.CreationTime); + } + Move(extractResults); + } + + void IFileRead.WaitForThread() => WaitForThread(thread: null, threadExceptions: null); + + string IFileRead.GetEventDescription() + { + string result = _Description.GetEventDescription(); + return result; + } + + List IFileRead.GetHeaderNames() + { + List results = _Description.GetHeaderNames(); + return results; + } + + string[] IFileRead.Move(Tuple> extractResults, string to, string from, string resolvedFileLocation, Exception exception) + { + string[] results = Move(extractResults, to, from, resolvedFileLocation, exception); + return results; + } + + JsonProperty[] IFileRead.GetDefault() + { + JsonProperty[] results = _Description.GetDefault(this, _Logistics); + return results; + } + + Dictionary IFileRead.GetDisplayNamesJsonElement() + { + Dictionary results = _Description.GetDisplayNamesJsonElement(this); + return results; + } + + List IFileRead.GetDescriptions(IFileRead fileRead, List tests, IProcessData processData) + { + List results = _Description.GetDescriptions(fileRead, _Logistics, tests, processData); + return results; + } + + Tuple> IFileRead.GetExtractResult(string reportFullPath, string eventName) + { + Tuple> results; + if (string.IsNullOrEmpty(eventName)) + throw new Exception(); + _ReportFullPath = reportFullPath; + DateTime dateTime = DateTime.Now; + results = GetExtractResult(reportFullPath, dateTime); + if (results.Item3 is null) + results = new Tuple>(results.Item1, Array.Empty(), JsonSerializer.Deserialize("[]"), results.Item4); + if (results.Item3.Length > 0 && _IsEAFHosted) + WritePDSF(this, results.Item3); + UpdateLastTicksDuration(DateTime.Now.Ticks - dateTime.Ticks); + return results; + } + + Tuple> IFileRead.ReExtract() + { + Tuple> results; + List headerNames = _Description.GetHeaderNames(); + Dictionary keyValuePairs = _Description.GetDisplayNamesJsonElement(this); + results = ReExtract(this, headerNames, keyValuePairs); + return results; + } + + private static int? GetKeyColumnIndex(string[] columns, string keyColumn) + { +#nullable enable + int? result = null; + for (int i = 0; i < columns.Length; i++) + { + if (columns[i] != keyColumn) + continue; + result = i; + break; + } + return result; + } + + private ReadOnlyCollection GetSystemStateValues(List lines, string[] columns, int keyColumnIndex) + { + List results = new(); + string[] values; + string? systemState; + string keyColumnValue; + for (int i = 7; i < lines.Count; i++) + { + values = lines[i].Split('\t'); + if (values.Length != columns.Length) + continue; + keyColumnValue = values[keyColumnIndex]; + if (string.IsNullOrEmpty(keyColumnValue)) + continue; + if (!_SystemStateToNames.TryGetValue(keyColumnValue, out systemState)) + continue; + if (results.Contains(systemState)) + continue; + results.Add(systemState); + } + return new(results); + } + + private void CopyFile(string reportFullPath) + { + string equipment; + string timestamp; + string[] columns; + DateTime dateTime; + List lines; + string systemState; + int? keyColumnIndex; + string checkFileName; + List headerLines = new(); + ReadOnlyCollection systemStateValues; + string missingKeyDirectory = Path.Combine(_FileConnectorConfiguration.AlternateTargetFolder, "Missing-Key"); + if (!Directory.Exists(missingKeyDirectory)) + _ = Directory.CreateDirectory(missingKeyDirectory); + string fileName = Path.GetFileName(reportFullPath); + string[] segments = fileName.Split('_'); + for (int z = 0; z < 1; z++) + { + if (segments.Length != 2) + continue; + equipment = segments[0]; + timestamp = segments[1].Split('.')[0]; + if (timestamp.Length != _TimestampFormat.Length) + continue; + headerLines.Clear(); + lines = File.ReadAllLines(reportFullPath).ToList(); + if (lines.Count < 8) + continue; + for (int i = 0; i < 6; i++) + { + headerLines.Add(lines[0]); + lines.RemoveAt(0); + } + if (lines[0].Length < 1 || lines[0][0] != '"' || !lines[0].StartsWith("\"Time\"")) + continue; + columns = lines[0].Split('\t'); + if (columns.Length < 3) + continue; + keyColumnIndex = GetKeyColumnIndex(columns, _KeyColumn); + if (keyColumnIndex is null) + { + File.Copy(reportFullPath, Path.Combine(_FileConnectorConfiguration.AlternateTargetFolder, missingKeyDirectory, fileName)); + continue; + } + systemStateValues = GetSystemStateValues(lines, columns, keyColumnIndex.Value); + if (systemStateValues.Count == 0) + { + File.Copy(reportFullPath, Path.Combine(_FileConnectorConfiguration.AlternateTargetFolder, missingKeyDirectory, fileName)); + continue; + } + lines.AddRange(headerLines); + systemState = string.Join("-", systemStateValues); + checkFileName = Path.Combine(_FileConnectorConfiguration.AlternateTargetFolder, $"{equipment}-{timestamp}-{systemState}.pdsf"); + File.WriteAllLines(checkFileName, lines); + // File.Delete(reportFullPath); + if (DateTime.TryParseExact(timestamp, _TimestampFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) + File.SetLastWriteTime(checkFileName, dateTime); + } + } + + private Tuple> GetExtractResult(string reportFullPath, DateTime _) + { + Tuple> results; + ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath); + _Logistics = new Logistics(reportFullPath, processDataStandardFormat); + SetFileParameterLotIDToLogisticsMID(); + JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat); + List descriptions = GetDuplicatorDescriptions(jsonElements); + Test[] tests = (from l in descriptions select (Test)l.Test).ToArray(); + if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0) + CopyFile(reportFullPath); + results = new Tuple>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics), tests, jsonElements, new List()); + return results; + } + +} \ No newline at end of file diff --git a/Adaptation/FileHandlers/R56/FileRead.cs b/Adaptation/FileHandlers/R56/FileRead.cs new file mode 100644 index 0000000..61507e7 --- /dev/null +++ b/Adaptation/FileHandlers/R56/FileRead.cs @@ -0,0 +1,238 @@ +using Adaptation.Eaf.Management.ConfigurationData.CellAutomation; +using Adaptation.Ifx.Eaf.EquipmentConnector.File.Configuration; +using Adaptation.Shared; +using Adaptation.Shared.Duplicator; +using Adaptation.Shared.Methods; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text.Json; + +namespace Adaptation.FileHandlers.R56; + +public class FileRead : Shared.FileRead, IFileRead +{ + + private readonly string _KeyColumn; + private readonly string _TimestampFormat; + private readonly ReadOnlyDictionary _SystemStateToNames; + + public FileRead(ISMTP smtp, Dictionary fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList modelObjectParameters, string equipmentDictionaryName, Dictionary> dummyRuns, Dictionary> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) : + base(new Description(), false, smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null) + { + _MinFileLength = 10; + _NullData = string.Empty; + _Logistics = new(this); + if (_FileParameter is null) + throw new Exception(cellInstanceConnectionName); + if (_ModelObjectParameterDefinitions is null) + throw new Exception(cellInstanceConnectionName); + if (!_IsDuplicator) + throw new Exception(cellInstanceConnectionName); + string[] segments; + Dictionary systemStateToNames = new(); + _KeyColumn = GetPropertyValue(cellInstanceConnectionName, modelObjectParameters, "ProcessDataStandardFormat.KeyColumn"); + _TimestampFormat = GetPropertyValue(cellInstanceConnectionName, modelObjectParameters, "ProcessDataStandardFormat.TimestampFormat"); + ModelObjectParameterDefinition[] systemStates = GetProperties(cellInstanceConnectionName, modelObjectParameters, "ProcessDataStandardFormat.SystemState"); + foreach (ModelObjectParameterDefinition modelObjectParameterDefinition in systemStates) + { + segments = modelObjectParameterDefinition.Value.Split('|'); + if (segments.Length != 2) + continue; + systemStateToNames.Add(segments[0], segments[1]); + } + _SystemStateToNames = new(systemStateToNames); + } + + void IFileRead.Move(Tuple> extractResults, Exception exception) + { + bool isErrorFile = exception is not null; + if (!isErrorFile && !string.IsNullOrEmpty(_Logistics.ReportFullPath)) + { + FileInfo fileInfo = new(_Logistics.ReportFullPath); + if (fileInfo.Exists && fileInfo.LastWriteTime < fileInfo.CreationTime) + File.SetLastWriteTime(_Logistics.ReportFullPath, fileInfo.CreationTime); + } + Move(extractResults); + } + + void IFileRead.WaitForThread() => WaitForThread(thread: null, threadExceptions: null); + + string IFileRead.GetEventDescription() + { + string result = _Description.GetEventDescription(); + return result; + } + + List IFileRead.GetHeaderNames() + { + List results = _Description.GetHeaderNames(); + return results; + } + + string[] IFileRead.Move(Tuple> extractResults, string to, string from, string resolvedFileLocation, Exception exception) + { + string[] results = Move(extractResults, to, from, resolvedFileLocation, exception); + return results; + } + + JsonProperty[] IFileRead.GetDefault() + { + JsonProperty[] results = _Description.GetDefault(this, _Logistics); + return results; + } + + Dictionary IFileRead.GetDisplayNamesJsonElement() + { + Dictionary results = _Description.GetDisplayNamesJsonElement(this); + return results; + } + + List IFileRead.GetDescriptions(IFileRead fileRead, List tests, IProcessData processData) + { + List results = _Description.GetDescriptions(fileRead, _Logistics, tests, processData); + return results; + } + + Tuple> IFileRead.GetExtractResult(string reportFullPath, string eventName) + { + Tuple> results; + if (string.IsNullOrEmpty(eventName)) + throw new Exception(); + _ReportFullPath = reportFullPath; + DateTime dateTime = DateTime.Now; + results = GetExtractResult(reportFullPath, dateTime); + if (results.Item3 is null) + results = new Tuple>(results.Item1, Array.Empty(), JsonSerializer.Deserialize("[]"), results.Item4); + if (results.Item3.Length > 0 && _IsEAFHosted) + WritePDSF(this, results.Item3); + UpdateLastTicksDuration(DateTime.Now.Ticks - dateTime.Ticks); + return results; + } + + Tuple> IFileRead.ReExtract() + { + Tuple> results; + List headerNames = _Description.GetHeaderNames(); + Dictionary keyValuePairs = _Description.GetDisplayNamesJsonElement(this); + results = ReExtract(this, headerNames, keyValuePairs); + return results; + } + + private static int? GetKeyColumnIndex(string[] columns, string keyColumn) + { +#nullable enable + int? result = null; + for (int i = 0; i < columns.Length; i++) + { + if (columns[i] != keyColumn) + continue; + result = i; + break; + } + return result; + } + + private ReadOnlyCollection GetSystemStateValues(List lines, string[] columns, int keyColumnIndex) + { + List results = new(); + string[] values; + string? systemState; + string keyColumnValue; + for (int i = 7; i < lines.Count; i++) + { + values = lines[i].Split('\t'); + if (values.Length != columns.Length) + continue; + keyColumnValue = values[keyColumnIndex]; + if (string.IsNullOrEmpty(keyColumnValue)) + continue; + if (!_SystemStateToNames.TryGetValue(keyColumnValue, out systemState)) + continue; + if (results.Contains(systemState)) + continue; + results.Add(systemState); + } + return new(results); + } + + private void CopyFile(string reportFullPath) + { + string equipment; + string timestamp; + string[] columns; + DateTime dateTime; + List lines; + string systemState; + int? keyColumnIndex; + string checkFileName; + List headerLines = new(); + ReadOnlyCollection systemStateValues; + string missingKeyDirectory = Path.Combine(_FileConnectorConfiguration.AlternateTargetFolder, "Missing-Key"); + if (!Directory.Exists(missingKeyDirectory)) + _ = Directory.CreateDirectory(missingKeyDirectory); + string fileName = Path.GetFileName(reportFullPath); + string[] segments = fileName.Split('_'); + for (int z = 0; z < 1; z++) + { + if (segments.Length != 2) + continue; + equipment = segments[0]; + timestamp = segments[1].Split('.')[0]; + if (timestamp.Length != _TimestampFormat.Length) + continue; + headerLines.Clear(); + lines = File.ReadAllLines(reportFullPath).ToList(); + if (lines.Count < 8) + continue; + for (int i = 0; i < 6; i++) + { + headerLines.Add(lines[0]); + lines.RemoveAt(0); + } + if (lines[0].Length < 1 || lines[0][0] != '"' || !lines[0].StartsWith("\"Time\"")) + continue; + columns = lines[0].Split('\t'); + if (columns.Length < 3) + continue; + keyColumnIndex = GetKeyColumnIndex(columns, _KeyColumn); + if (keyColumnIndex is null) + { + File.Copy(reportFullPath, Path.Combine(_FileConnectorConfiguration.AlternateTargetFolder, missingKeyDirectory, fileName)); + continue; + } + systemStateValues = GetSystemStateValues(lines, columns, keyColumnIndex.Value); + if (systemStateValues.Count == 0) + { + File.Copy(reportFullPath, Path.Combine(_FileConnectorConfiguration.AlternateTargetFolder, missingKeyDirectory, fileName)); + continue; + } + lines.AddRange(headerLines); + systemState = string.Join("-", systemStateValues); + checkFileName = Path.Combine(_FileConnectorConfiguration.AlternateTargetFolder, $"{equipment}-{timestamp}-{systemState}.pdsf"); + File.WriteAllLines(checkFileName, lines); + // File.Delete(reportFullPath); + if (DateTime.TryParseExact(timestamp, _TimestampFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) + File.SetLastWriteTime(checkFileName, dateTime); + } + } + + private Tuple> GetExtractResult(string reportFullPath, DateTime _) + { + Tuple> results; + ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath); + _Logistics = new Logistics(reportFullPath, processDataStandardFormat); + SetFileParameterLotIDToLogisticsMID(); + JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat); + List descriptions = GetDuplicatorDescriptions(jsonElements); + Test[] tests = (from l in descriptions select (Test)l.Test).ToArray(); + if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0) + CopyFile(reportFullPath); + results = new Tuple>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics), tests, jsonElements, new List()); + return results; + } + +} \ No newline at end of file diff --git a/Adaptation/Shared/ProcessDataStandardFormat.cs b/Adaptation/Shared/ProcessDataStandardFormat.cs index 3737852..82237b2 100644 --- a/Adaptation/Shared/ProcessDataStandardFormat.cs +++ b/Adaptation/Shared/ProcessDataStandardFormat.cs @@ -399,7 +399,8 @@ internal class ProcessDataStandardFormat lines.Add(line); } string? json = null; - if (processDataStandardFormat.Footer is not null && processDataStandardFormat.Footer.Count > 0) { + if (processDataStandardFormat.Footer is not null && processDataStandardFormat.Footer.Count > 0) + { Dictionary footerKeyValuePairs = GetFooterKeyValuePairs(processDataStandardFormat.Footer); Dictionary> logisticKeyValuePairs = GetLogisticKeyValuePairs(processDataStandardFormat.Footer, footerKeyValuePairs); json = JsonSerializer.Serialize(logisticKeyValuePairs, DictionaryStringDictionaryStringStringSourceGenerationContext.Default.DictionaryStringDictionaryStringString); @@ -439,51 +440,72 @@ internal class ProcessDataStandardFormat return result; } - private static Dictionary GetFooterKeyValuePairs(ReadOnlyCollection footerLines) { + private static Dictionary GetFooterKeyValuePairs(ReadOnlyCollection footerLines) + { Dictionary results = new(); string[] segments; - foreach (string footerLine in footerLines) { + foreach (string footerLine in footerLines) + { segments = footerLine.Split('\t'); - if (segments.Length != 2 || string.IsNullOrEmpty(segments[1].Trim())) { + if (segments.Length != 2 || string.IsNullOrEmpty(segments[1].Trim())) + { continue; } - if (segments[1].Contains(';')) { + if (segments[1].Contains(';')) + { continue; - } else { + } + else + { + if (results.ContainsKey(segments[0])) + { + continue; + } results.Add(segments[0], segments[1]); } } return results; } - private static Dictionary> GetLogisticKeyValuePairs(ReadOnlyCollection footerLines, Dictionary footerKeyValuePairs) { + private static Dictionary> GetLogisticKeyValuePairs(ReadOnlyCollection footerLines, Dictionary footerKeyValuePairs) + { Dictionary> results = new(); string[] segments; string[] subSegments; string[] subSubSegments; Dictionary? keyValue; results.Add("Footer", footerKeyValuePairs); - foreach (string footerLine in footerLines) { + foreach (string footerLine in footerLines) + { segments = footerLine.Split('\t'); - if (segments.Length != 2 || string.IsNullOrEmpty(segments[1].Trim())) { + if (segments.Length != 2 || string.IsNullOrEmpty(segments[1].Trim())) + { continue; } - if (!segments[1].Contains(';') || !segments[1].Contains('=')) { + if (!segments[1].Contains(';') || !segments[1].Contains('=')) + { continue; - } else { + } + else + { subSegments = segments[1].Split(';'); - if (subSegments.Length < 1) { + if (subSegments.Length < 1) + { continue; } - if (!results.TryGetValue(segments[0], out keyValue)) { + if (!results.TryGetValue(segments[0], out keyValue)) + { results.Add(segments[0], new()); - if (!results.TryGetValue(segments[0], out keyValue)) { + if (!results.TryGetValue(segments[0], out keyValue)) + { throw new Exception(); } } - foreach (string segment in subSegments) { + foreach (string segment in subSegments) + { subSubSegments = segment.Split('='); - if (subSubSegments.Length != 2) { + if (subSubSegments.Length != 2) + { continue; } keyValue.Add(subSubSegments[0], subSubSegments[1]); @@ -496,6 +518,8 @@ internal class ProcessDataStandardFormat internal static void Write(string path, ProcessDataStandardFormat processDataStandardFormat, List? wsResults) { List results = new(); + if (processDataStandardFormat.InputPDSF is null) + throw new NullReferenceException(nameof(processDataStandardFormat.InputPDSF)); if (processDataStandardFormat.Sequence is null) throw new NullReferenceException(nameof(processDataStandardFormat.Sequence)); string endOffset = "E#######T"; @@ -533,24 +557,22 @@ internal class ProcessDataStandardFormat } } results.Add("END_HEADER"); - if (processDataStandardFormat.InputPDSF is not null) - { - results.Add(string.Empty); - List hyphens = new(); - results.AddRange(processDataStandardFormat.InputPDSF.Header.Select(l => l.Replace('\t', '|'))); - results.Add($"|{string.Join("|", processDataStandardFormat.InputPDSF.Columns)}|"); - for (int i = 0; i < processDataStandardFormat.InputPDSF.Columns.Count; i++) - hyphens.Add('-'); - results.Add($"|{string.Join("|", hyphens)}|"); - results.AddRange(processDataStandardFormat.InputPDSF.Body.Select(l => l.Replace('\t', '|'))); - results.Add(string.Empty); - results.AddRange(processDataStandardFormat.InputPDSF.Footer.Select(l => l.Replace('\t', '|'))); - results.Add(string.Empty); - results.Add("EOF"); - results.Add(string.Empty); - string json = GetJson(processDataStandardFormat); - results.Add(json); - } + results.Add(string.Empty); + List hyphens = new(); + results.AddRange(processDataStandardFormat.InputPDSF.Header.Select(l => $"|{l.Replace('\t', '|')}|")); + results.Add(string.Empty); + results.Add($"|{string.Join("|", processDataStandardFormat.InputPDSF.Columns)}|"); + for (int i = 0; i < processDataStandardFormat.InputPDSF.Columns.Count; i++) + hyphens.Add('-'); + results.Add($"|{string.Join("|", hyphens)}|"); + results.AddRange(processDataStandardFormat.InputPDSF.Body.Select(l => $"|{l.Replace('\t', '|')}|")); + results.Add(string.Empty); + results.AddRange(processDataStandardFormat.InputPDSF.Footer.Select(l => $"|{l.Replace('\t', '|')}|")); + results.Add(string.Empty); + results.Add("EOF"); + results.Add(string.Empty); + string json = GetJson(processDataStandardFormat); + results.Add(json); File.WriteAllText(path, string.Join(Environment.NewLine, results)); } @@ -842,5 +864,6 @@ internal partial class JsonElementCollectionSourceGenerationContext : JsonSerial [JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)] [JsonSerializable(typeof(Dictionary>))] -internal partial class DictionaryStringDictionaryStringStringSourceGenerationContext : JsonSerializerContext { +internal partial class DictionaryStringDictionaryStringStringSourceGenerationContext : JsonSerializerContext +{ } \ No newline at end of file diff --git a/Adaptation/_Tests/CreateSelfDescription/Production/v2.60.0/DEP08CEPIEPSILON.cs b/Adaptation/_Tests/CreateSelfDescription/Production/v2.60.0/DEP08CEPIEPSILON.cs index 6996c3d..09194c0 100644 --- a/Adaptation/_Tests/CreateSelfDescription/Production/v2.60.0/DEP08CEPIEPSILON.cs +++ b/Adaptation/_Tests/CreateSelfDescription/Production/v2.60.0/DEP08CEPIEPSILON.cs @@ -137,5 +137,16 @@ public class DEP08CEPIEPSILON : EAFLoggingUnitTesting EAFLoggingUnitTesting.Logger.LogInformation(string.Concat(methodBase.Name, " - Exit")); } + [Ignore] + [TestMethod] + public void Production__v2_60_0__DEP08CEPIEPSILON__InfinityQS() + { + string check = "*.pdsf"; + MethodBase methodBase = new StackFrame().GetMethod(); + EAFLoggingUnitTesting.Logger.LogInformation(string.Concat(methodBase.Name, " - Getting configuration")); + _ = AdaptationTesting.GetWriteConfigurationGetFileRead(methodBase, check, EAFLoggingUnitTesting.AdaptationTesting); + EAFLoggingUnitTesting.Logger.LogInformation(string.Concat(methodBase.Name, " - Exit")); + } + } #endif \ No newline at end of file diff --git a/Adaptation/_Tests/Extract/Production/v2.60.0/DEP08CEPIEPSILON.cs b/Adaptation/_Tests/Extract/Production/v2.60.0/DEP08CEPIEPSILON.cs index a62cfe8..f4f6e8c 100644 --- a/Adaptation/_Tests/Extract/Production/v2.60.0/DEP08CEPIEPSILON.cs +++ b/Adaptation/_Tests/Extract/Production/v2.60.0/DEP08CEPIEPSILON.cs @@ -96,5 +96,21 @@ public class DEP08CEPIEPSILON [TestMethod] public void Production__v2_60_0__DEP08CEPIEPSILON__R55() => _DEP08CEPIEPSILON.Production__v2_60_0__DEP08CEPIEPSILON__R55(); +#if DEBUG + [Ignore] +#endif + [TestMethod] + public void Production__v2_60_0__DEP08CEPIEPSILON__InfinityQS638895639451629988__First() + { + string check = "*.pdsf"; + MethodBase methodBase = new StackFrame().GetMethod(); + _DEP08CEPIEPSILON.Production__v2_60_0__DEP08CEPIEPSILON__InfinityQS(); + string[] variables = _DEP08CEPIEPSILON.AdaptationTesting.GetVariables(methodBase, check, validatePDSF: false); + IFileRead fileRead = _DEP08CEPIEPSILON.AdaptationTesting.Get(methodBase, sourceFileLocation: variables[2], sourceFileFilter: variables[3], useCyclicalForDescription: false); + Logistics logistics = new(fileRead); + _ = AdaptationTesting.ReExtractCompareUpdatePassDirectory(variables, fileRead, logistics); + NonThrowTryCatch(); + } + } #endif \ No newline at end of file diff --git a/DEP08CEPIEPSILON.csproj b/DEP08CEPIEPSILON.csproj index f5b15d8..ece16f3 100644 --- a/DEP08CEPIEPSILON.csproj +++ b/DEP08CEPIEPSILON.csproj @@ -107,15 +107,18 @@ + + + + + - -