Split violations from Markdown
ProcessDataStandardFormat over Tuple MoveMatchingFiles to use ProcessDataStandardFormatMapping
This commit is contained in:
parent
40177bfb51
commit
2fc83bb54d
8
Adaptation/.vscode/launch.json
vendored
8
Adaptation/.vscode/launch.json
vendored
@ -4,13 +4,7 @@
|
|||||||
"name": ".NET Core Attach",
|
"name": ".NET Core Attach",
|
||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "attach",
|
"request": "attach",
|
||||||
"processId": 25140
|
"processId": 23840
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "node",
|
|
||||||
"request": "launch",
|
|
||||||
"name": "node Launch Current Opened File",
|
|
||||||
"program": "${file}"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
20
Adaptation/.vscode/tasks.json
vendored
20
Adaptation/.vscode/tasks.json
vendored
@ -92,6 +92,26 @@
|
|||||||
"command": "code ../MESAFIBACKLOG.csproj",
|
"command": "code ../MESAFIBACKLOG.csproj",
|
||||||
"problemMatcher": []
|
"problemMatcher": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"label": "Readme",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "code ../README.md",
|
||||||
|
"problemMatcher": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "File-Folder-Helper AOT s X Day-Helper-2025-03-20",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe",
|
||||||
|
"args": [
|
||||||
|
"s",
|
||||||
|
"X",
|
||||||
|
"L:/DevOps/EAF-Mesa-Integration/MESAFIBACKLOG",
|
||||||
|
"Day-Helper-2025-03-20",
|
||||||
|
"false",
|
||||||
|
"4"
|
||||||
|
],
|
||||||
|
"problemMatcher": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"label": "Git Config",
|
"label": "Git Config",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
|
@ -103,7 +103,9 @@ public class FileRead : Shared.FileRead, IFileRead
|
|||||||
{
|
{
|
||||||
Tuple<string, Test[], JsonElement[], List<FileInfo>> results = new(string.Empty, null, null, new List<FileInfo>());
|
Tuple<string, Test[], JsonElement[], List<FileInfo>> results = new(string.Empty, null, null, new List<FileInfo>());
|
||||||
_TickOffset ??= 0; // new FileInfo(reportFullPath).LastWriteTime.Ticks - dateTime.Ticks;
|
_TickOffset ??= 0; // new FileInfo(reportFullPath).LastWriteTime.Ticks - dateTime.Ticks;
|
||||||
_Logistics = new Logistics(reportFullPath, $"LOGISTICS_1{'\t'}A_JOBID={"BACKLOG"};A_MES_ENTITY={"BACKLOG"};");
|
string[] lines = new string[] { string.Empty, "NUM_DATA_ROWS", $"LOGISTICS_1{'\t'}A_JOBID={"BACKLOG"};A_MES_ENTITY={"BACKLOG"};" };
|
||||||
|
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath, lines);
|
||||||
|
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
|
||||||
SetFileParameterLotIDToLogisticsMID();
|
SetFileParameterLotIDToLogisticsMID();
|
||||||
if (_Logistics.FileInfo.Length < _MinFileLength)
|
if (_Logistics.FileInfo.Length < _MinFileLength)
|
||||||
results.Item4.Add(_Logistics.FileInfo);
|
results.Item4.Add(_Logistics.FileInfo);
|
||||||
|
@ -120,15 +120,15 @@ public class FileRead : Shared.FileRead, IFileRead
|
|||||||
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
|
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
|
||||||
{
|
{
|
||||||
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
|
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
|
||||||
ProcessData processData = ProcessDataStandardFormat.GetProcessData(reportFullPath);
|
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
|
||||||
_Logistics = new Logistics(reportFullPath, processData.Logistics);
|
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
|
||||||
SetFileParameterLotIDToLogisticsMID();
|
SetFileParameterLotIDToLogisticsMID();
|
||||||
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processData);
|
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
|
||||||
List<Shared.Properties.IDescription> descriptions = GetDuplicatorDescriptions(jsonElements);
|
List<Shared.Properties.IDescription> descriptions = GetDuplicatorDescriptions(jsonElements);
|
||||||
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
|
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
|
||||||
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
|
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
|
||||||
FileCopy(reportFullPath, dateTime, descriptions);
|
FileCopy(reportFullPath, dateTime, descriptions);
|
||||||
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(processData.Logistics, tests, jsonElements, new List<FileInfo>());
|
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List<FileInfo>());
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,9 +120,10 @@ public class FileRead : Shared.FileRead, IFileRead
|
|||||||
if (dateTime == DateTime.MinValue)
|
if (dateTime == DateTime.MinValue)
|
||||||
throw new ArgumentNullException(nameof(dateTime));
|
throw new ArgumentNullException(nameof(dateTime));
|
||||||
string logisticsSequence = _Logistics.Sequence.ToString();
|
string logisticsSequence = _Logistics.Sequence.ToString();
|
||||||
|
string day = $"{_Logistics.DateTimeFromSequence:yyyy-MM-dd}";
|
||||||
string weekOfYear = _Calendar.GetWeekOfYear(_Logistics.DateTimeFromSequence, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00");
|
string weekOfYear = _Calendar.GetWeekOfYear(_Logistics.DateTimeFromSequence, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00");
|
||||||
string weekDirectory = $"{_Logistics.DateTimeFromSequence:yyyy}_Week_{weekOfYear}{@"\"}{_Logistics.DateTimeFromSequence:yyyy-MM-dd}";
|
string weekDirectory = $"{_Logistics.DateTimeFromSequence:yyyy}_Week_{weekOfYear}";
|
||||||
string destinationArchiveDirectory = Path.Combine(_JobIdArchiveParentDirectory, _Logistics.JobID, weekDirectory);
|
string destinationArchiveDirectory = Path.Combine(_JobIdArchiveParentDirectory, _Logistics.JobID, weekDirectory, day);
|
||||||
if (!Directory.Exists(destinationArchiveDirectory))
|
if (!Directory.Exists(destinationArchiveDirectory))
|
||||||
_ = Directory.CreateDirectory(destinationArchiveDirectory);
|
_ = Directory.CreateDirectory(destinationArchiveDirectory);
|
||||||
string jobIdDirectory = Path.Combine(_JobIdParentDirectory, _Logistics.JobID);
|
string jobIdDirectory = Path.Combine(_JobIdParentDirectory, _Logistics.JobID);
|
||||||
@ -144,15 +145,15 @@ public class FileRead : Shared.FileRead, IFileRead
|
|||||||
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
|
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
|
||||||
{
|
{
|
||||||
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
|
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
|
||||||
ProcessData processData = ProcessDataStandardFormat.GetProcessData(reportFullPath);
|
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
|
||||||
_Logistics = new Logistics(reportFullPath, processData.Logistics);
|
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
|
||||||
SetFileParameterLotIDToLogisticsMID();
|
SetFileParameterLotIDToLogisticsMID();
|
||||||
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processData);
|
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
|
||||||
List<Shared.Properties.IDescription> descriptions = GetDuplicatorDescriptions(jsonElements);
|
List<Shared.Properties.IDescription> descriptions = GetDuplicatorDescriptions(jsonElements);
|
||||||
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
|
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
|
||||||
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
|
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
|
||||||
MoveArchive(reportFullPath, dateTime);
|
MoveArchive(reportFullPath, dateTime);
|
||||||
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(processData.Logistics, tests, jsonElements, new List<FileInfo>());
|
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List<FileInfo>());
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ public class CellInstanceConnectionName
|
|||||||
nameof(Priority) => new Priority.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null),
|
nameof(Priority) => new Priority.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null),
|
||||||
nameof(Processed) => new Processed.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null),
|
nameof(Processed) => new Processed.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null),
|
||||||
nameof(SPaCe) => new SPaCe.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null),
|
nameof(SPaCe) => new SPaCe.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null),
|
||||||
|
nameof(Violation) => new Violation.FileRead(smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null),
|
||||||
_ => throw new Exception($"\"{cellInstanceConnectionName}\" not mapped")
|
_ => throw new Exception($"\"{cellInstanceConnectionName}\" not mapped")
|
||||||
};
|
};
|
||||||
return result;
|
return result;
|
||||||
|
@ -119,15 +119,15 @@ public class FileRead : Shared.FileRead, IFileRead
|
|||||||
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
|
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
|
||||||
{
|
{
|
||||||
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
|
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
|
||||||
ProcessData processData = ProcessDataStandardFormat.GetProcessData(reportFullPath);
|
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
|
||||||
_Logistics = new Logistics(reportFullPath, processData.Logistics);
|
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
|
||||||
SetFileParameterLotIDToLogisticsMID();
|
SetFileParameterLotIDToLogisticsMID();
|
||||||
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processData);
|
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
|
||||||
List<Shared.Properties.IDescription> descriptions = GetDuplicatorDescriptions(jsonElements);
|
List<Shared.Properties.IDescription> descriptions = GetDuplicatorDescriptions(jsonElements);
|
||||||
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
|
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
|
||||||
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
|
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
|
||||||
FileCopy(reportFullPath, dateTime, descriptions);
|
FileCopy(reportFullPath, dateTime, descriptions);
|
||||||
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(processData.Logistics, tests, jsonElements, new List<FileInfo>());
|
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List<FileInfo>());
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +103,9 @@ public class FileRead : Shared.FileRead, IFileRead
|
|||||||
{
|
{
|
||||||
Tuple<string, Test[], JsonElement[], List<FileInfo>> results = new(string.Empty, null, null, new List<FileInfo>());
|
Tuple<string, Test[], JsonElement[], List<FileInfo>> results = new(string.Empty, null, null, new List<FileInfo>());
|
||||||
_TickOffset ??= 0; // new FileInfo(reportFullPath).LastWriteTime.Ticks - dateTime.Ticks;
|
_TickOffset ??= 0; // new FileInfo(reportFullPath).LastWriteTime.Ticks - dateTime.Ticks;
|
||||||
_Logistics = new Logistics(reportFullPath, $"LOGISTICS_1{'\t'}A_JOBID={"BACKLOG"};A_MES_ENTITY={"BACKLOG"};");
|
string[] lines = new string[] { string.Empty, "NUM_DATA_ROWS", $"LOGISTICS_1{'\t'}A_JOBID={"BACKLOG"};A_MES_ENTITY={"BACKLOG"};" };
|
||||||
|
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath, lines);
|
||||||
|
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
|
||||||
SetFileParameterLotIDToLogisticsMID();
|
SetFileParameterLotIDToLogisticsMID();
|
||||||
if (_Logistics.FileInfo.Length < _MinFileLength)
|
if (_Logistics.FileInfo.Length < _MinFileLength)
|
||||||
results.Item4.Add(_Logistics.FileInfo);
|
results.Item4.Add(_Logistics.FileInfo);
|
||||||
|
@ -13,6 +13,8 @@ using System.Text.Json.Serialization;
|
|||||||
|
|
||||||
namespace Adaptation.FileHandlers.Kanban;
|
namespace Adaptation.FileHandlers.Kanban;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
public class ProcessData : IProcessData
|
public class ProcessData : IProcessData
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -22,125 +24,25 @@ public class ProcessData : IProcessData
|
|||||||
|
|
||||||
private readonly ILog _Log;
|
private readonly ILog _Log;
|
||||||
|
|
||||||
public ProcessData(IFileRead fileRead, Logistics logistics, Calendar calendar, string targetFileLocation, string url, List<FileInfo> fileInfoCollection)
|
|
||||||
{
|
|
||||||
if (fileRead.IsEAFHosted)
|
|
||||||
{ }
|
|
||||||
if (url is null)
|
|
||||||
throw new ArgumentNullException(nameof(url));
|
|
||||||
_Details = new List<object>();
|
|
||||||
_Log = LogManager.GetLogger(typeof(ProcessData));
|
|
||||||
WriteFiles(fileRead, logistics, calendar, targetFileLocation, fileInfoCollection);
|
|
||||||
}
|
|
||||||
|
|
||||||
string IProcessData.GetCurrentReactor(IFileRead fileRead, Logistics logistics, Dictionary<string, string> reactors) =>
|
string IProcessData.GetCurrentReactor(IFileRead fileRead, Logistics logistics, Dictionary<string, string> reactors) =>
|
||||||
throw new Exception(string.Concat("See ", nameof(WriteFiles)));
|
throw new Exception(string.Concat("See ", nameof(WriteFiles)));
|
||||||
|
|
||||||
Tuple<string, Test[], JsonElement[], List<FileInfo>> IProcessData.GetResults(IFileRead fileRead, Logistics logistics, List<FileInfo> fileInfoCollection) =>
|
Tuple<string, Test[], JsonElement[], List<FileInfo>> IProcessData.GetResults(IFileRead fileRead, Logistics logistics, List<FileInfo> fileInfoCollection) =>
|
||||||
new(logistics.Logistics1[0], Array.Empty<Test>(), Array.Empty<JsonElement>(), fileInfoCollection);
|
new(logistics.Logistics1[0], Array.Empty<Test>(), Array.Empty<JsonElement>(), fileInfoCollection);
|
||||||
|
|
||||||
#nullable enable
|
public ProcessData(IFileRead fileRead, Logistics logistics, Calendar calendar, string targetFileLocation, string url, List<FileInfo> fileInfoCollection)
|
||||||
|
|
||||||
internal static List<Description> GetDescriptions(JsonElement[] jsonElements)
|
|
||||||
{
|
{
|
||||||
List<Description> results = new();
|
if (fileRead.IsEAFHosted)
|
||||||
Description? description;
|
|
||||||
JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString };
|
|
||||||
foreach (JsonElement jsonElement in jsonElements)
|
|
||||||
{
|
{
|
||||||
if (jsonElement.ValueKind != JsonValueKind.Object)
|
|
||||||
throw new Exception();
|
|
||||||
description = JsonSerializer.Deserialize<Description>(jsonElement.ToString(), jsonSerializerOptions);
|
|
||||||
if (description is null)
|
|
||||||
continue;
|
|
||||||
results.Add(description);
|
|
||||||
}
|
}
|
||||||
return results;
|
if (url is null)
|
||||||
|
throw new ArgumentNullException(nameof(url));
|
||||||
|
_Details = new List<object>();
|
||||||
|
_Log = LogManager.GetLogger(typeof(ProcessData));
|
||||||
|
WriteFiles(fileRead, logistics, calendar, targetFileLocation, fileInfoCollection);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ReadOnlyDictionary<int, Record> GetKeyValuePairs(ReadOnlyDictionary<int, WorkItem> keyValuePairs, bool keepRelations)
|
|
||||||
{
|
|
||||||
Dictionary<int, Record> results = new();
|
|
||||||
Record record;
|
|
||||||
List<bool> nests = new();
|
|
||||||
WorkItem? parentWorkItem;
|
|
||||||
ReadOnlyCollection<Record> childRecords;
|
|
||||||
ReadOnlyCollection<Record> relatedRecords;
|
|
||||||
ReadOnlyCollection<Record> successorRecords;
|
|
||||||
foreach (KeyValuePair<int, WorkItem> keyValuePair in keyValuePairs)
|
|
||||||
{
|
|
||||||
nests.Clear();
|
|
||||||
if (keyValuePair.Value.Parent is null)
|
|
||||||
parentWorkItem = null;
|
|
||||||
else
|
|
||||||
_ = keyValuePairs.TryGetValue(keyValuePair.Value.Parent.Value, out parentWorkItem);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
childRecords = Record.GetKeyValuePairs(keyValuePairs, keyValuePair.Value, "Child", nests, keepRelations); // Forward
|
|
||||||
relatedRecords = Record.GetKeyValuePairs(keyValuePairs, keyValuePair.Value, "Related", nests, keepRelations); // Related
|
|
||||||
successorRecords = Record.GetKeyValuePairs(keyValuePairs, keyValuePair.Value, "Successor", nests, keepRelations); // Forward
|
|
||||||
// predecessorRecords = Record.GetKeyValuePairs(keyValuePairs, keyValuePair.Value, "Predecessor", nests, keepRelations); // Reverse
|
|
||||||
record = Record.Get(keyValuePair.Value, parentWorkItem, childRecords, relatedRecords, successorRecords, keepRelations);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
record = new(keyValuePair.Value, parentWorkItem, Array.Empty<Record>(), Array.Empty<Record>(), Array.Empty<Record>());
|
|
||||||
}
|
|
||||||
results.Add(keyValuePair.Key, record);
|
|
||||||
}
|
|
||||||
return new(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ReadOnlyDictionary<int, Record> GetWorkItems(WorkItem[] workItems, bool keepRelations)
|
|
||||||
{
|
|
||||||
ReadOnlyDictionary<int, Record> results;
|
|
||||||
Dictionary<int, WorkItem> keyValuePairs = new();
|
|
||||||
foreach (WorkItem workItem in workItems)
|
|
||||||
keyValuePairs.Add(workItem.Id, workItem);
|
|
||||||
results = GetKeyValuePairs(new(keyValuePairs), keepRelations);
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void WriteFiles(IFileRead fileRead, DirectoryInfo tasksDirectory, Record[] records)
|
|
||||||
{
|
|
||||||
string old;
|
|
||||||
string json;
|
|
||||||
string checkFile;
|
|
||||||
WorkItem workItem;
|
|
||||||
foreach (Record record in records)
|
|
||||||
{
|
|
||||||
workItem = record.WorkItem;
|
|
||||||
json = JsonSerializer.Serialize(workItem, WorkItemSourceGenerationContext.Default.WorkItem);
|
|
||||||
checkFile = Path.Combine(tasksDirectory.FullName, $"{workItem.Id}.json");
|
|
||||||
old = File.Exists(checkFile) ? File.ReadAllText(checkFile) : string.Empty;
|
|
||||||
if (!fileRead.IsEAFHosted || old == json)
|
|
||||||
continue;
|
|
||||||
File.WriteAllText(checkFile, json);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetTaskText(string directory) =>
|
|
||||||
string.Join(Environment.NewLine, new string[]
|
|
||||||
{
|
|
||||||
"{",
|
|
||||||
"\"version\": \"2.0.0\",",
|
|
||||||
"\"tasks\": [",
|
|
||||||
"{",
|
|
||||||
"\"label\": \"File-Folder-Helper AOT s X Day-Helper-2025-02-04\",",
|
|
||||||
"\"type\": \"shell\",",
|
|
||||||
"\"command\": \"L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe\",",
|
|
||||||
"\"args\": [",
|
|
||||||
"\"s\",",
|
|
||||||
"\"X\",",
|
|
||||||
$"\"{directory.Replace('\\', '/')}\",",
|
|
||||||
"\"Day-Helper-2025-02-04\",",
|
|
||||||
"],",
|
|
||||||
"\"problemMatcher\": []",
|
|
||||||
"}",
|
|
||||||
"]",
|
|
||||||
"}",
|
|
||||||
});
|
|
||||||
|
|
||||||
private static void WriteFiles(IFileRead fileRead, Calendar calendar, string destinationDirectory, bool keepRelations, WorkItem[] workItems)
|
private static void WriteFiles(IFileRead fileRead, Calendar calendar, string destinationDirectory, bool keepRelations, WorkItem[] workItems)
|
||||||
{
|
{
|
||||||
string json;
|
string json;
|
||||||
@ -193,6 +95,22 @@ public class ProcessData : IProcessData
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void WriteFiles(IFileRead fileRead, Logistics logistics, Calendar calendar, string destinationDirectory, List<FileInfo> fileInfoCollection)
|
||||||
|
{
|
||||||
|
if (fileInfoCollection is null)
|
||||||
|
throw new ArgumentNullException(nameof(fileInfoCollection));
|
||||||
|
bool keepRelations = true;
|
||||||
|
string json = File.ReadAllText(logistics.ReportFullPath);
|
||||||
|
WorkItem[]? workItems = JsonSerializer.Deserialize<WorkItem[]>(json);
|
||||||
|
if (workItems is null)
|
||||||
|
throw new Exception(nameof(workItems));
|
||||||
|
_Details.Add(workItems);
|
||||||
|
if (!Directory.Exists(destinationDirectory))
|
||||||
|
_ = Directory.CreateDirectory(destinationDirectory);
|
||||||
|
WriteFiles(fileRead, calendar, destinationDirectory, workItems);
|
||||||
|
WriteFiles(fileRead, calendar, destinationDirectory, keepRelations, workItems);
|
||||||
|
}
|
||||||
|
|
||||||
private static void WriteFiles(IFileRead fileRead, Calendar calendar, string destinationDirectory, WorkItem[] workItems)
|
private static void WriteFiles(IFileRead fileRead, Calendar calendar, string destinationDirectory, WorkItem[] workItems)
|
||||||
{
|
{
|
||||||
string old;
|
string old;
|
||||||
@ -215,20 +133,104 @@ public class ProcessData : IProcessData
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WriteFiles(IFileRead fileRead, Logistics logistics, Calendar calendar, string destinationDirectory, List<FileInfo> fileInfoCollection)
|
private static ReadOnlyDictionary<int, Record> GetWorkItems(WorkItem[] workItems, bool keepRelations)
|
||||||
{
|
{
|
||||||
if (fileInfoCollection is null)
|
ReadOnlyDictionary<int, Record> results;
|
||||||
throw new ArgumentNullException(nameof(fileInfoCollection));
|
Dictionary<int, WorkItem> keyValuePairs = new();
|
||||||
bool keepRelations = true;
|
foreach (WorkItem workItem in workItems)
|
||||||
string json = File.ReadAllText(logistics.ReportFullPath);
|
keyValuePairs.Add(workItem.Id, workItem);
|
||||||
WorkItem[]? workItems = JsonSerializer.Deserialize<WorkItem[]>(json);
|
results = GetKeyValuePairs(new(keyValuePairs), keepRelations);
|
||||||
if (workItems is null)
|
return results;
|
||||||
throw new Exception(nameof(workItems));
|
}
|
||||||
_Details.Add(workItems);
|
|
||||||
if (!Directory.Exists(destinationDirectory))
|
private static ReadOnlyDictionary<int, Record> GetKeyValuePairs(ReadOnlyDictionary<int, WorkItem> keyValuePairs, bool keepRelations)
|
||||||
_ = Directory.CreateDirectory(destinationDirectory);
|
{
|
||||||
WriteFiles(fileRead, calendar, destinationDirectory, workItems);
|
Dictionary<int, Record> results = new();
|
||||||
WriteFiles(fileRead, calendar, destinationDirectory, keepRelations, workItems);
|
Record record;
|
||||||
|
List<bool> nests = new();
|
||||||
|
WorkItem? parentWorkItem;
|
||||||
|
ReadOnlyCollection<Record> childRecords;
|
||||||
|
ReadOnlyCollection<Record> relatedRecords;
|
||||||
|
ReadOnlyCollection<Record> successorRecords;
|
||||||
|
foreach (KeyValuePair<int, WorkItem> keyValuePair in keyValuePairs)
|
||||||
|
{
|
||||||
|
nests.Clear();
|
||||||
|
if (keyValuePair.Value.Parent is null)
|
||||||
|
parentWorkItem = null;
|
||||||
|
else
|
||||||
|
_ = keyValuePairs.TryGetValue(keyValuePair.Value.Parent.Value, out parentWorkItem);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
childRecords = Record.GetKeyValuePairs(keyValuePairs, keyValuePair.Value, "Child", nests, keepRelations); // Forward
|
||||||
|
relatedRecords = Record.GetKeyValuePairs(keyValuePairs, keyValuePair.Value, "Related", nests, keepRelations); // Related
|
||||||
|
successorRecords = Record.GetKeyValuePairs(keyValuePairs, keyValuePair.Value, "Successor", nests, keepRelations); // Forward
|
||||||
|
// predecessorRecords = Record.GetKeyValuePairs(keyValuePairs, keyValuePair.Value, "Predecessor", nests, keepRelations); // Reverse
|
||||||
|
record = Record.Get(keyValuePair.Value, parentWorkItem, childRecords, relatedRecords, successorRecords, keepRelations);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
record = new(keyValuePair.Value, parentWorkItem, Array.Empty<Record>(), Array.Empty<Record>(), Array.Empty<Record>());
|
||||||
|
}
|
||||||
|
results.Add(keyValuePair.Key, record);
|
||||||
|
}
|
||||||
|
return new(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetTaskText(string directory) =>
|
||||||
|
string.Join(Environment.NewLine, new string[]
|
||||||
|
{
|
||||||
|
"{",
|
||||||
|
"\"version\": \"2.0.0\",",
|
||||||
|
"\"tasks\": [",
|
||||||
|
"{",
|
||||||
|
"\"label\": \"File-Folder-Helper AOT s X Day-Helper-2025-02-04\",",
|
||||||
|
"\"type\": \"shell\",",
|
||||||
|
"\"command\": \"L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe\",",
|
||||||
|
"\"args\": [",
|
||||||
|
"\"s\",",
|
||||||
|
"\"X\",",
|
||||||
|
$"\"{directory.Replace('\\', '/')}\",",
|
||||||
|
"\"Day-Helper-2025-02-04\",",
|
||||||
|
"],",
|
||||||
|
"\"problemMatcher\": []",
|
||||||
|
"}",
|
||||||
|
"]",
|
||||||
|
"}",
|
||||||
|
});
|
||||||
|
|
||||||
|
private static void WriteFiles(IFileRead fileRead, DirectoryInfo tasksDirectory, Record[] records)
|
||||||
|
{
|
||||||
|
string old;
|
||||||
|
string json;
|
||||||
|
string checkFile;
|
||||||
|
WorkItem workItem;
|
||||||
|
foreach (Record record in records)
|
||||||
|
{
|
||||||
|
workItem = record.WorkItem;
|
||||||
|
json = JsonSerializer.Serialize(workItem, WorkItemSourceGenerationContext.Default.WorkItem);
|
||||||
|
checkFile = Path.Combine(tasksDirectory.FullName, $"{workItem.Id}.json");
|
||||||
|
old = File.Exists(checkFile) ? File.ReadAllText(checkFile) : string.Empty;
|
||||||
|
if (!fileRead.IsEAFHosted || old == json)
|
||||||
|
continue;
|
||||||
|
File.WriteAllText(checkFile, json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static List<Description> GetDescriptions(JsonElement[] jsonElements)
|
||||||
|
{
|
||||||
|
List<Description> results = new();
|
||||||
|
Description? description;
|
||||||
|
JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString };
|
||||||
|
foreach (JsonElement jsonElement in jsonElements)
|
||||||
|
{
|
||||||
|
if (jsonElement.ValueKind != JsonValueKind.Object)
|
||||||
|
throw new Exception();
|
||||||
|
description = JsonSerializer.Deserialize<Description>(jsonElement.ToString(), jsonSerializerOptions);
|
||||||
|
if (description is null)
|
||||||
|
continue;
|
||||||
|
results.Add(description);
|
||||||
|
}
|
||||||
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -107,7 +107,9 @@ public class FileRead : Shared.FileRead, IFileRead
|
|||||||
{
|
{
|
||||||
Tuple<string, Test[], JsonElement[], List<FileInfo>> results = new(string.Empty, null, null, new List<FileInfo>());
|
Tuple<string, Test[], JsonElement[], List<FileInfo>> results = new(string.Empty, null, null, new List<FileInfo>());
|
||||||
_TickOffset ??= 0; // new FileInfo(reportFullPath).LastWriteTime.Ticks - dateTime.Ticks;
|
_TickOffset ??= 0; // new FileInfo(reportFullPath).LastWriteTime.Ticks - dateTime.Ticks;
|
||||||
_Logistics = new Logistics(reportFullPath, $"LOGISTICS_1{'\t'}A_JOBID={"BACKLOG"};A_MES_ENTITY={"BACKLOG"};");
|
string[] lines = new string[] { string.Empty, "NUM_DATA_ROWS", $"LOGISTICS_1{'\t'}A_JOBID={"BACKLOG"};A_MES_ENTITY={"BACKLOG"};" };
|
||||||
|
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath, lines);
|
||||||
|
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
|
||||||
SetFileParameterLotIDToLogisticsMID();
|
SetFileParameterLotIDToLogisticsMID();
|
||||||
if (_Logistics.FileInfo.Length < _MinFileLength)
|
if (_Logistics.FileInfo.Length < _MinFileLength)
|
||||||
results.Item4.Add(_Logistics.FileInfo);
|
results.Item4.Add(_Logistics.FileInfo);
|
||||||
|
@ -13,6 +13,8 @@ using System.Text.Json.Serialization;
|
|||||||
|
|
||||||
namespace Adaptation.FileHandlers.Markdown;
|
namespace Adaptation.FileHandlers.Markdown;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
public class ProcessData : IProcessData
|
public class ProcessData : IProcessData
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -22,38 +24,46 @@ public class ProcessData : IProcessData
|
|||||||
|
|
||||||
private readonly ILog _Log;
|
private readonly ILog _Log;
|
||||||
|
|
||||||
public ProcessData(IFileRead fileRead, Logistics logistics, string targetFileLocation, string url, ReadOnlyCollection<string> workItemTypes, List<FileInfo> fileInfoCollection)
|
|
||||||
{
|
|
||||||
if (fileRead.IsEAFHosted)
|
|
||||||
{ }
|
|
||||||
_Details = new List<object>();
|
|
||||||
_Log = LogManager.GetLogger(typeof(ProcessData));
|
|
||||||
WriteFiles(fileRead, logistics, url, workItemTypes, targetFileLocation, fileInfoCollection);
|
|
||||||
}
|
|
||||||
|
|
||||||
string IProcessData.GetCurrentReactor(IFileRead fileRead, Logistics logistics, Dictionary<string, string> reactors) =>
|
string IProcessData.GetCurrentReactor(IFileRead fileRead, Logistics logistics, Dictionary<string, string> reactors) =>
|
||||||
throw new Exception(string.Concat("See ", nameof(WriteFiles)));
|
throw new Exception(string.Concat("See ", nameof(WriteFiles)));
|
||||||
|
|
||||||
Tuple<string, Test[], JsonElement[], List<FileInfo>> IProcessData.GetResults(IFileRead fileRead, Logistics logistics, List<FileInfo> fileInfoCollection) =>
|
Tuple<string, Test[], JsonElement[], List<FileInfo>> IProcessData.GetResults(IFileRead fileRead, Logistics logistics, List<FileInfo> fileInfoCollection) =>
|
||||||
new(logistics.Logistics1[0], Array.Empty<Test>(), Array.Empty<JsonElement>(), fileInfoCollection);
|
new(logistics.Logistics1[0], Array.Empty<Test>(), Array.Empty<JsonElement>(), fileInfoCollection);
|
||||||
|
|
||||||
#nullable enable
|
public ProcessData(IFileRead fileRead, Logistics logistics, string targetFileLocation, string url, ReadOnlyCollection<string> workItemTypes, List<FileInfo> fileInfoCollection)
|
||||||
|
|
||||||
internal static List<Description> GetDescriptions(JsonElement[] jsonElements)
|
|
||||||
{
|
{
|
||||||
List<Description> results = new();
|
if (fileRead.IsEAFHosted)
|
||||||
Description? description;
|
|
||||||
JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString };
|
|
||||||
foreach (JsonElement jsonElement in jsonElements)
|
|
||||||
{
|
{
|
||||||
if (jsonElement.ValueKind != JsonValueKind.Object)
|
|
||||||
throw new Exception();
|
|
||||||
description = JsonSerializer.Deserialize<Description>(jsonElement.ToString(), jsonSerializerOptions);
|
|
||||||
if (description is null)
|
|
||||||
continue;
|
|
||||||
results.Add(description);
|
|
||||||
}
|
}
|
||||||
return results;
|
_Details = new List<object>();
|
||||||
|
_Log = LogManager.GetLogger(typeof(ProcessData));
|
||||||
|
WriteFiles(fileRead, logistics, url, workItemTypes, targetFileLocation, fileInfoCollection);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteFiles(IFileRead fileRead, string destinationDirectory, List<FileInfo> fileInfoCollection, ReadOnlyCollection<string> lines, ReadOnlyCollection<Record> records, string fileName)
|
||||||
|
{
|
||||||
|
string markdown = string.Join(Environment.NewLine, lines);
|
||||||
|
string markdownFile = Path.Combine(destinationDirectory, $"{fileName}.md");
|
||||||
|
string markdownOld = !File.Exists(markdownFile) ? string.Empty : File.ReadAllText(markdownFile);
|
||||||
|
if (markdown != markdownOld)
|
||||||
|
File.WriteAllText(markdownFile, markdown);
|
||||||
|
if (!fileRead.IsEAFHosted)
|
||||||
|
fileInfoCollection.Add(new(markdownFile));
|
||||||
|
string html = CommonMark.CommonMarkConverter.Convert(markdown).Replace("<a href", "<a target='_blank' href");
|
||||||
|
string htmlFile = Path.Combine(destinationDirectory, $"{fileName}.html");
|
||||||
|
string htmlOld = !File.Exists(htmlFile) ? string.Empty : File.ReadAllText(htmlFile);
|
||||||
|
if (html != htmlOld)
|
||||||
|
File.WriteAllText(htmlFile, html);
|
||||||
|
if (!fileRead.IsEAFHosted)
|
||||||
|
fileInfoCollection.Add(new(htmlFile));
|
||||||
|
string json = JsonSerializer.Serialize(records, new JsonSerializerOptions() { WriteIndented = true });
|
||||||
|
string jsonFile = Path.Combine(destinationDirectory, $"{fileName}.json");
|
||||||
|
string jsonOld = !File.Exists(jsonFile) ? string.Empty : File.ReadAllText(jsonFile);
|
||||||
|
if (json != jsonOld)
|
||||||
|
File.WriteAllText(jsonFile, json);
|
||||||
|
if (!fileRead.IsEAFHosted)
|
||||||
|
fileInfoCollection.Add(new(jsonFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WriteFiles(IFileRead fileRead, Logistics logistics, string url, ReadOnlyCollection<string> workItemTypes, string destinationDirectory, List<FileInfo> fileInfoCollection)
|
private void WriteFiles(IFileRead fileRead, Logistics logistics, string url, ReadOnlyCollection<string> workItemTypes, string destinationDirectory, List<FileInfo> fileInfoCollection)
|
||||||
@ -83,13 +93,11 @@ public class ProcessData : IProcessData
|
|||||||
ReadOnlyCollection<Record> results;
|
ReadOnlyCollection<Record> results;
|
||||||
ReadOnlyDictionary<int, Record> keyValuePairs = GetWorkItems(workItems, keepRelations);
|
ReadOnlyDictionary<int, Record> keyValuePairs = GetWorkItems(workItems, keepRelations);
|
||||||
ReadOnlyCollection<Record> records = new(keyValuePairs.Values.ToArray());
|
ReadOnlyCollection<Record> records = new(keyValuePairs.Values.ToArray());
|
||||||
ReadOnlyCollection<string> userStoryWorkItemTypes = new(new string[] { "User Story" });
|
|
||||||
ReadOnlyCollection<string> bugFeatureWorkItemTypes = new(new string[] { "Bug", "Feature" });
|
ReadOnlyCollection<string> bugFeatureWorkItemTypes = new(new string[] { "Bug", "Feature" });
|
||||||
ReadOnlyCollection<string> bugUserStoryWorkItemTypes = new(new string[] { "Bug", "User Story" });
|
ReadOnlyCollection<string> bugUserStoryWorkItemTypes = new(new string[] { "Bug", "User Story" });
|
||||||
ReadOnlyCollection<string> bugUserStoryTaskWorkItemTypes = new(new string[] { "Bug", "User Story", "Task" });
|
|
||||||
messages.AddRange(WriteFile(fileRead, destinationDirectory, fileInfoCollection, records, "records"));
|
messages.AddRange(WriteFile(fileRead, destinationDirectory, fileInfoCollection, records, "records"));
|
||||||
messages.AddRange(WriteWithPartentsFile(fileRead, destinationDirectory, fileInfoCollection, records, bugFeatureWorkItemTypes, "bugs-features-with-parents"));
|
messages.AddRange(WriteWithParentsFile(fileRead, destinationDirectory, fileInfoCollection, records, bugFeatureWorkItemTypes, "bugs-features-with-parents"));
|
||||||
messages.AddRange(WriteWithPartentsFile(fileRead, destinationDirectory, fileInfoCollection, records, bugUserStoryWorkItemTypes, "bugs-user-stories-with-parents"));
|
messages.AddRange(WriteWithParentsFile(fileRead, destinationDirectory, fileInfoCollection, records, bugUserStoryWorkItemTypes, "bugs-user-stories-with-parents"));
|
||||||
foreach (string workItemType in workItemTypes)
|
foreach (string workItemType in workItemTypes)
|
||||||
{
|
{
|
||||||
lines.Clear();
|
lines.Clear();
|
||||||
@ -100,98 +108,10 @@ public class ProcessData : IProcessData
|
|||||||
WriteFiles(fileRead, destinationDirectory, fileInfoCollection, new(lines), results, workItemType);
|
WriteFiles(fileRead, destinationDirectory, fileInfoCollection, new(lines), results, workItemType);
|
||||||
_Details.Add(results);
|
_Details.Add(results);
|
||||||
}
|
}
|
||||||
{
|
|
||||||
lines.Clear();
|
|
||||||
string workItemType = "Feature";
|
|
||||||
lines.Add($"# {nameof(FeatureCheckIterationPath122508)}");
|
|
||||||
lines.Add(string.Empty);
|
|
||||||
results = FeatureCheckIterationPath122508(url, lines, bugUserStoryTaskWorkItemTypes, keyValuePairs, workItemType);
|
|
||||||
WriteFiles(fileRead, destinationDirectory, fileInfoCollection, new(lines), results, "check-122508");
|
|
||||||
_Details.Add(results);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
lines.Clear();
|
|
||||||
string workItemType = "Feature";
|
|
||||||
lines.Add($"# {nameof(FeatureCheckTag122514)}");
|
|
||||||
lines.Add(string.Empty);
|
|
||||||
results = FeatureCheckTag122514(url, lines, bugUserStoryWorkItemTypes, keyValuePairs, workItemType);
|
|
||||||
WriteFiles(fileRead, destinationDirectory, fileInfoCollection, new(lines), results, "check-122514");
|
|
||||||
_Details.Add(results);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
lines.Clear();
|
|
||||||
string workItemType = "Feature";
|
|
||||||
lines.Add($"# {nameof(FeatureCheckPriority126169)}");
|
|
||||||
lines.Add(string.Empty);
|
|
||||||
results = FeatureCheckPriority126169(url, lines, bugUserStoryWorkItemTypes, keyValuePairs, workItemType);
|
|
||||||
WriteFiles(fileRead, destinationDirectory, fileInfoCollection, new(lines), results, "check-126169");
|
|
||||||
_Details.Add(results);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
lines.Clear();
|
|
||||||
string workItemType = "Feature";
|
|
||||||
lines.Add($"# {nameof(FeatureCheckState123066)}");
|
|
||||||
lines.Add(string.Empty);
|
|
||||||
results = FeatureCheckState123066(url, lines, bugUserStoryTaskWorkItemTypes, keyValuePairs, workItemType);
|
|
||||||
WriteFiles(fileRead, destinationDirectory, fileInfoCollection, new(lines), results, "check-123066");
|
|
||||||
_Details.Add(results);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
lines.Clear();
|
|
||||||
string workItemType = "Feature";
|
|
||||||
lines.Add($"# {nameof(FeatureCheckState123067)}");
|
|
||||||
lines.Add(string.Empty);
|
|
||||||
results = FeatureCheckState123067(url, lines, bugUserStoryTaskWorkItemTypes, keyValuePairs, workItemType);
|
|
||||||
WriteFiles(fileRead, destinationDirectory, fileInfoCollection, new(lines), results, "check-123067");
|
|
||||||
_Details.Add(results);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
lines.Clear();
|
|
||||||
string workItemType = "Feature";
|
|
||||||
lines.Add($"# {nameof(FeatureCheckStart122517)}");
|
|
||||||
lines.Add(string.Empty);
|
|
||||||
results = FeatureCheckStart122517(url, lines, bugUserStoryTaskWorkItemTypes, keyValuePairs, workItemType);
|
|
||||||
WriteFiles(fileRead, destinationDirectory, fileInfoCollection, new(lines), results, "check-122517");
|
|
||||||
_Details.Add(results);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
lines.Clear();
|
|
||||||
string workItemType = "User Story";
|
|
||||||
lines.Add($"# {nameof(UserStoryCheckIterationPath228385)}");
|
|
||||||
lines.Add(string.Empty);
|
|
||||||
results = UserStoryCheckIterationPath228385(url, lines, userStoryWorkItemTypes, keyValuePairs, workItemType);
|
|
||||||
WriteFiles(fileRead, destinationDirectory, fileInfoCollection, new(lines), results, "check-228385");
|
|
||||||
_Details.Add(results);
|
|
||||||
}
|
|
||||||
if (messages.Count > 0)
|
if (messages.Count > 0)
|
||||||
throw new Exception($"{messages.Count}{Environment.NewLine}{string.Join(Environment.NewLine, messages)}");
|
throw new Exception($"{messages.Count}{Environment.NewLine}{string.Join(Environment.NewLine, messages)}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void WriteFiles(IFileRead fileRead, string destinationDirectory, List<FileInfo> fileInfoCollection, ReadOnlyCollection<string> lines, ReadOnlyCollection<Record> records, string fileName)
|
|
||||||
{
|
|
||||||
string markdown = string.Join(Environment.NewLine, lines);
|
|
||||||
string markdownFile = Path.Combine(destinationDirectory, $"{fileName}.md");
|
|
||||||
string markdownOld = !File.Exists(markdownFile) ? string.Empty : File.ReadAllText(markdownFile);
|
|
||||||
if (markdown != markdownOld)
|
|
||||||
File.WriteAllText(markdownFile, markdown);
|
|
||||||
if (!fileRead.IsEAFHosted)
|
|
||||||
fileInfoCollection.Add(new(markdownFile));
|
|
||||||
string html = CommonMark.CommonMarkConverter.Convert(markdown).Replace("<a href", "<a target='_blank' href");
|
|
||||||
string htmlFile = Path.Combine(destinationDirectory, $"{fileName}.html");
|
|
||||||
string htmlOld = !File.Exists(htmlFile) ? string.Empty : File.ReadAllText(htmlFile);
|
|
||||||
if (html != htmlOld)
|
|
||||||
File.WriteAllText(htmlFile, html);
|
|
||||||
if (!fileRead.IsEAFHosted)
|
|
||||||
fileInfoCollection.Add(new(htmlFile));
|
|
||||||
string json = JsonSerializer.Serialize(records, new JsonSerializerOptions() { WriteIndented = true });
|
|
||||||
string jsonFile = Path.Combine(destinationDirectory, $"{fileName}.json");
|
|
||||||
string jsonOld = !File.Exists(jsonFile) ? string.Empty : File.ReadAllText(jsonFile);
|
|
||||||
if (json != jsonOld)
|
|
||||||
File.WriteAllText(jsonFile, json);
|
|
||||||
if (!fileRead.IsEAFHosted)
|
|
||||||
fileInfoCollection.Add(new(jsonFile));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ReadOnlyDictionary<int, Record> GetWorkItems(IEnumerable<WorkItem> workItems, bool keepRelations)
|
private static ReadOnlyDictionary<int, Record> GetWorkItems(IEnumerable<WorkItem> workItems, bool keepRelations)
|
||||||
{
|
{
|
||||||
ReadOnlyDictionary<int, Record> results;
|
ReadOnlyDictionary<int, Record> results;
|
||||||
@ -202,6 +122,74 @@ public class ProcessData : IProcessData
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyDictionary<int, Record> GetKeyValuePairs(ReadOnlyDictionary<int, WorkItem> keyValuePairs, bool keepRelations)
|
||||||
|
{
|
||||||
|
Dictionary<int, Record> results = new();
|
||||||
|
Record record;
|
||||||
|
List<bool> nests = new();
|
||||||
|
WorkItem? parentWorkItem;
|
||||||
|
ReadOnlyCollection<Record> childRecords;
|
||||||
|
ReadOnlyCollection<Record> relatedRecords;
|
||||||
|
ReadOnlyCollection<Record> successorRecords;
|
||||||
|
foreach (KeyValuePair<int, WorkItem> keyValuePair in keyValuePairs)
|
||||||
|
{
|
||||||
|
nests.Clear();
|
||||||
|
if (keyValuePair.Value.Parent is null)
|
||||||
|
parentWorkItem = null;
|
||||||
|
else
|
||||||
|
_ = keyValuePairs.TryGetValue(keyValuePair.Value.Parent.Value, out parentWorkItem);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
childRecords = Record.GetKeyValuePairs(keyValuePairs, keyValuePair.Value, "Child", nests, keepRelations); // Forward
|
||||||
|
relatedRecords = Record.GetKeyValuePairs(keyValuePairs, keyValuePair.Value, "Related", nests, keepRelations); // Related
|
||||||
|
successorRecords = Record.GetKeyValuePairs(keyValuePairs, keyValuePair.Value, "Successor", nests, keepRelations); // Forward
|
||||||
|
// predecessorRecords = Record.GetKeyValuePairs(keyValuePairs, keyValuePair.Value, "Predecessor", nests, keepRelations); // Reverse
|
||||||
|
record = Record.Get(keyValuePair.Value, parentWorkItem, childRecords, relatedRecords, successorRecords, keepRelations);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
record = new(keyValuePair.Value, parentWorkItem, Array.Empty<Record>(), Array.Empty<Record>(), Array.Empty<Record>());
|
||||||
|
}
|
||||||
|
results.Add(keyValuePair.Key, record);
|
||||||
|
}
|
||||||
|
return new(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyCollection<string> WriteFile(IFileRead fileRead, string destinationDirectory, List<FileInfo> fileInfoCollection, ReadOnlyCollection<Record> records, string fileName)
|
||||||
|
{
|
||||||
|
List<string> results = new();
|
||||||
|
string? json = GetJson(records, results);
|
||||||
|
string jsonFile = Path.Combine(destinationDirectory, $"{fileName}.json");
|
||||||
|
string jsonOld = !File.Exists(jsonFile) ? string.Empty : File.ReadAllText(jsonFile);
|
||||||
|
if (!string.IsNullOrEmpty(json) && json != jsonOld)
|
||||||
|
File.WriteAllText(jsonFile, json);
|
||||||
|
if (!fileRead.IsEAFHosted)
|
||||||
|
fileInfoCollection.Add(new(jsonFile));
|
||||||
|
return new(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyCollection<string> WriteWithParentsFile(IFileRead fileRead, string destinationDirectory, List<FileInfo> fileInfoCollection, ReadOnlyCollection<Record> records, ReadOnlyCollection<string> workItemTypes, string fileName)
|
||||||
|
{
|
||||||
|
List<string> results = new();
|
||||||
|
Record record;
|
||||||
|
List<Record> filtered = new();
|
||||||
|
foreach (Record r in records)
|
||||||
|
{
|
||||||
|
if (r.WorkItem.State == "Removed" || !workItemTypes.Contains(r.WorkItem.WorkItemType))
|
||||||
|
continue;
|
||||||
|
record = new(r.WorkItem, r.Parent, Array.Empty<Record>(), Array.Empty<Record>(), Array.Empty<Record>());
|
||||||
|
filtered.Add(record);
|
||||||
|
}
|
||||||
|
string? json = GetJson(filtered, results);
|
||||||
|
string jsonFile = Path.Combine(destinationDirectory, $"{fileName}.json");
|
||||||
|
string jsonOld = !File.Exists(jsonFile) ? string.Empty : File.ReadAllText(jsonFile);
|
||||||
|
if (!string.IsNullOrEmpty(json) && json != jsonOld)
|
||||||
|
File.WriteAllText(jsonFile, json);
|
||||||
|
if (!fileRead.IsEAFHosted)
|
||||||
|
fileInfoCollection.Add(new(jsonFile));
|
||||||
|
return new(results);
|
||||||
|
}
|
||||||
|
|
||||||
private static string? GetJson(IEnumerable<Record> records, List<string> results)
|
private static string? GetJson(IEnumerable<Record> records, List<string> results)
|
||||||
{
|
{
|
||||||
string? result;
|
string? result;
|
||||||
@ -221,39 +209,22 @@ public class ProcessData : IProcessData
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ReadOnlyCollection<string> WriteFile(IFileRead fileRead, string destinationDirectory, List<FileInfo> fileInfoCollection, ReadOnlyCollection<Record> records, string fileName)
|
private static void AppendLines(List<char> spaces, List<string> lines, Record record, bool condensed, bool sprintOnly)
|
||||||
{
|
{
|
||||||
List<string> results = new();
|
string line;
|
||||||
string? json = GetJson(records, results);
|
spaces.Add('\t');
|
||||||
string jsonFile = Path.Combine(destinationDirectory, $"{fileName}.json");
|
WorkItem workItem;
|
||||||
string jsonOld = !File.Exists(jsonFile) ? string.Empty : File.ReadAllText(jsonFile);
|
if (record.Children is not null)
|
||||||
if (!string.IsNullOrEmpty(json) && json != jsonOld)
|
|
||||||
File.WriteAllText(jsonFile, json);
|
|
||||||
if (!fileRead.IsEAFHosted)
|
|
||||||
fileInfoCollection.Add(new(jsonFile));
|
|
||||||
return new(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ReadOnlyCollection<string> WriteWithPartentsFile(IFileRead fileRead, string destinationDirectory, List<FileInfo> fileInfoCollection, ReadOnlyCollection<Record> records, ReadOnlyCollection<string> workItemTypes, string fileName)
|
|
||||||
{
|
|
||||||
List<string> results = new();
|
|
||||||
List<Record> filtered = new();
|
|
||||||
Record record;
|
|
||||||
foreach (Record r in records)
|
|
||||||
{
|
{
|
||||||
if (r.WorkItem.State == "Removed" || !workItemTypes.Contains(r.WorkItem.WorkItemType))
|
foreach (Record child in record.Children)
|
||||||
continue;
|
{
|
||||||
record = new(r.WorkItem, r.Parent, Array.Empty<Record>(), Array.Empty<Record>(), Array.Empty<Record>());
|
workItem = child.WorkItem;
|
||||||
filtered.Add(record);
|
line = GetLine(spaces, workItem, child, condensed, sprintOnly).TrimEnd();
|
||||||
|
lines.Add(line);
|
||||||
|
AppendLines(spaces, lines, child, condensed, sprintOnly);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
string? json = GetJson(filtered, results);
|
spaces.RemoveAt(0);
|
||||||
string jsonFile = Path.Combine(destinationDirectory, $"{fileName}.json");
|
|
||||||
string jsonOld = !File.Exists(jsonFile) ? string.Empty : File.ReadAllText(jsonFile);
|
|
||||||
if (!string.IsNullOrEmpty(json) && json != jsonOld)
|
|
||||||
File.WriteAllText(jsonFile, json);
|
|
||||||
if (!fileRead.IsEAFHosted)
|
|
||||||
fileInfoCollection.Add(new(jsonFile));
|
|
||||||
return new(results);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AppendLines(string url, List<char> spaces, List<string> lines, ReadOnlyCollection<Record> records, string workItemType)
|
private static void AppendLines(string url, List<char> spaces, List<string> lines, ReadOnlyCollection<Record> records, string workItemType)
|
||||||
@ -304,57 +275,6 @@ public class ProcessData : IProcessData
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AppendLines(List<char> spaces, List<string> lines, Record record, bool condensed, bool sprintOnly)
|
|
||||||
{
|
|
||||||
string line;
|
|
||||||
spaces.Add('\t');
|
|
||||||
WorkItem workItem;
|
|
||||||
if (record.Children is not null)
|
|
||||||
{
|
|
||||||
foreach (Record child in record.Children)
|
|
||||||
{
|
|
||||||
workItem = child.WorkItem;
|
|
||||||
line = GetLine(spaces, workItem, child, condensed, sprintOnly).TrimEnd();
|
|
||||||
lines.Add(line);
|
|
||||||
AppendLines(spaces, lines, child, condensed, sprintOnly);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spaces.RemoveAt(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ReadOnlyDictionary<int, Record> GetKeyValuePairs(ReadOnlyDictionary<int, WorkItem> keyValuePairs, bool keepRelations)
|
|
||||||
{
|
|
||||||
Dictionary<int, Record> results = new();
|
|
||||||
Record record;
|
|
||||||
List<bool> nests = new();
|
|
||||||
WorkItem? parentWorkItem;
|
|
||||||
ReadOnlyCollection<Record> childRecords;
|
|
||||||
ReadOnlyCollection<Record> relatedRecords;
|
|
||||||
ReadOnlyCollection<Record> successorRecords;
|
|
||||||
foreach (KeyValuePair<int, WorkItem> keyValuePair in keyValuePairs)
|
|
||||||
{
|
|
||||||
nests.Clear();
|
|
||||||
if (keyValuePair.Value.Parent is null)
|
|
||||||
parentWorkItem = null;
|
|
||||||
else
|
|
||||||
_ = keyValuePairs.TryGetValue(keyValuePair.Value.Parent.Value, out parentWorkItem);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
childRecords = Record.GetKeyValuePairs(keyValuePairs, keyValuePair.Value, "Child", nests, keepRelations); // Forward
|
|
||||||
relatedRecords = Record.GetKeyValuePairs(keyValuePairs, keyValuePair.Value, "Related", nests, keepRelations); // Related
|
|
||||||
successorRecords = Record.GetKeyValuePairs(keyValuePairs, keyValuePair.Value, "Successor", nests, keepRelations); // Forward
|
|
||||||
// predecessorRecords = Record.GetKeyValuePairs(keyValuePairs, keyValuePair.Value, "Predecessor", nests, keepRelations); // Reverse
|
|
||||||
record = Record.Get(keyValuePair.Value, parentWorkItem, childRecords, relatedRecords, successorRecords, keepRelations);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
record = new(keyValuePair.Value, parentWorkItem, Array.Empty<Record>(), Array.Empty<Record>(), Array.Empty<Record>());
|
|
||||||
}
|
|
||||||
results.Add(keyValuePair.Key, record);
|
|
||||||
}
|
|
||||||
return new(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetLine(List<char> spaces, WorkItem workItem, Record record, bool condensed, bool sprintOnly)
|
private static string GetLine(List<char> spaces, WorkItem workItem, Record record, bool condensed, bool sprintOnly)
|
||||||
{
|
{
|
||||||
string result;
|
string result;
|
||||||
@ -368,485 +288,21 @@ public class ProcessData : IProcessData
|
|||||||
private static string GetClosed(WorkItem workItem) =>
|
private static string GetClosed(WorkItem workItem) =>
|
||||||
workItem.State != "Closed" ? "[ ]" : "[x]";
|
workItem.State != "Closed" ? "[ ]" : "[x]";
|
||||||
|
|
||||||
private static void FilterChildren(ReadOnlyCollection<string> workItemTypes, Record record, List<Record> results)
|
internal static List<Description> GetDescriptions(JsonElement[] jsonElements)
|
||||||
{
|
{
|
||||||
if (record.Children is not null)
|
List<Description> results = new();
|
||||||
|
Description? description;
|
||||||
|
JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString };
|
||||||
|
foreach (JsonElement jsonElement in jsonElements)
|
||||||
{
|
{
|
||||||
foreach (Record r in record.Children)
|
if (jsonElement.ValueKind != JsonValueKind.Object)
|
||||||
{
|
throw new Exception();
|
||||||
if (!workItemTypes.Contains(r.WorkItem.WorkItemType))
|
description = JsonSerializer.Deserialize<Description>(jsonElement.ToString(), jsonSerializerOptions);
|
||||||
continue;
|
if (description is null)
|
||||||
results.Add(r);
|
continue;
|
||||||
FilterChildren(workItemTypes, r, results);
|
results.Add(description);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static ReadOnlyCollection<Record> FilterChildren(ReadOnlyCollection<string> workItemTypes, Record record)
|
|
||||||
{
|
|
||||||
List<Record> results = new();
|
|
||||||
FilterChildren(workItemTypes, record, results);
|
|
||||||
return new(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int GetState(WorkItem workItem) =>
|
|
||||||
workItem.State switch
|
|
||||||
{
|
|
||||||
"New" => 1,
|
|
||||||
"Active" => 2,
|
|
||||||
"Resolved" => 3,
|
|
||||||
"Closed" => 4,
|
|
||||||
"Removed" => 5,
|
|
||||||
_ => 8
|
|
||||||
};
|
|
||||||
|
|
||||||
private static ReadOnlyCollection<Record> GetMaxIterationPaths122508(ReadOnlyCollection<Record> records)
|
|
||||||
{
|
|
||||||
List<Record> results;
|
|
||||||
List<Record>? collection;
|
|
||||||
Dictionary<string, List<Record>> keyValuePairs = new();
|
|
||||||
foreach (Record record in records)
|
|
||||||
{
|
|
||||||
if (!keyValuePairs.TryGetValue(record.WorkItem.IterationPath, out collection))
|
|
||||||
{
|
|
||||||
keyValuePairs.Add(record.WorkItem.IterationPath, new());
|
|
||||||
if (!keyValuePairs.TryGetValue(record.WorkItem.IterationPath, out collection))
|
|
||||||
throw new Exception();
|
|
||||||
|
|
||||||
}
|
|
||||||
collection.Add(record);
|
|
||||||
}
|
|
||||||
string? max = keyValuePairs.Keys.Max();
|
|
||||||
results = string.IsNullOrEmpty(max) ? new() : keyValuePairs[max];
|
|
||||||
return results.AsReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ReadOnlyCollection<Record> FeatureCheckIterationPath122508(string url, List<string> lines, ReadOnlyCollection<string> workItemTypes, ReadOnlyDictionary<int, Record> keyValuePairs, string workItemType)
|
|
||||||
{
|
|
||||||
List<Record> results = new();
|
|
||||||
Record record;
|
|
||||||
List<string> violations = new();
|
|
||||||
List<string> collection = new();
|
|
||||||
ReadOnlyCollection<Record> records;
|
|
||||||
ReadOnlyCollection<Record> maxIterationPaths;
|
|
||||||
foreach (KeyValuePair<int, Record> keyValuePair in keyValuePairs)
|
|
||||||
{
|
|
||||||
record = keyValuePair.Value;
|
|
||||||
if (record.WorkItem.State is "Removed")
|
|
||||||
continue;
|
|
||||||
if (!record.WorkItem.IterationPath.Contains('\\'))
|
|
||||||
continue;
|
|
||||||
if (record.WorkItem.WorkItemType != workItemType)
|
|
||||||
continue;
|
|
||||||
collection.Clear();
|
|
||||||
violations.Clear();
|
|
||||||
if (record.Children is null || record.Children.Length == 0)
|
|
||||||
continue;
|
|
||||||
records = FilterChildren(workItemTypes, record);
|
|
||||||
maxIterationPaths = GetMaxIterationPaths122508(records);
|
|
||||||
foreach (Record r in maxIterationPaths)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(r.WorkItem.IterationPath) || record.WorkItem.IterationPath == r.WorkItem.IterationPath)
|
|
||||||
continue;
|
|
||||||
violations.Add($"<a target='_blank' href='{url}{r.WorkItem.Id}'>{r.WorkItem.Id}</a>:{r.WorkItem.IterationPath};");
|
|
||||||
}
|
|
||||||
if (violations.Count > 0)
|
|
||||||
{
|
|
||||||
collection.Insert(0, string.Empty);
|
|
||||||
collection.Insert(0, $"## {record.WorkItem.AssignedTo} - {record.WorkItem.Id} - {record.WorkItem.Title}");
|
|
||||||
lines.AddRange(collection);
|
|
||||||
violations.Insert(0, $"IterationPath:{record.WorkItem.IterationPath};");
|
|
||||||
results.Add(Record.GetWithoutNesting(record, string.Join(" ", violations)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ReadOnlyCollection<Record> GetWorkItemsNotMatching122514(Record record, ReadOnlyCollection<Record> records)
|
|
||||||
{
|
|
||||||
List<Record> results = new();
|
|
||||||
string[] segments;
|
|
||||||
string[] parentTags = record.WorkItem.Tags.Split(';').Select(l => l.Trim()).ToArray();
|
|
||||||
foreach (Record r in records)
|
|
||||||
{
|
|
||||||
segments = string.IsNullOrEmpty(r.WorkItem.Tags) ? Array.Empty<string>() : r.WorkItem.Tags.Split(';').Select(l => l.Trim()).ToArray();
|
|
||||||
if (segments.Length > 0 && parentTags.Any(l => segments.Contains(l)))
|
|
||||||
continue;
|
|
||||||
results.Add(r);
|
|
||||||
}
|
|
||||||
return new(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ReadOnlyCollection<Record> FeatureCheckTag122514(string url, List<string> lines, ReadOnlyCollection<string> workItemTypes, ReadOnlyDictionary<int, Record> keyValuePairs, string workItemType)
|
|
||||||
{
|
|
||||||
List<Record> results = new();
|
|
||||||
Record record;
|
|
||||||
List<string> collection = new();
|
|
||||||
List<string> violations = new();
|
|
||||||
ReadOnlyCollection<Record> records;
|
|
||||||
ReadOnlyCollection<Record> recordsNotMatching;
|
|
||||||
foreach (KeyValuePair<int, Record> keyValuePair in keyValuePairs)
|
|
||||||
{
|
|
||||||
record = keyValuePair.Value;
|
|
||||||
if (record.WorkItem.State is "Removed")
|
|
||||||
continue;
|
|
||||||
if (record.WorkItem.WorkItemType != workItemType)
|
|
||||||
continue;
|
|
||||||
collection.Clear();
|
|
||||||
violations.Clear();
|
|
||||||
if (record.Children is null || record.Children.Length == 0)
|
|
||||||
continue;
|
|
||||||
if (string.IsNullOrEmpty(record.WorkItem.Tags))
|
|
||||||
recordsNotMatching = new(new Record[] { record });
|
|
||||||
else
|
|
||||||
{
|
|
||||||
records = FilterChildren(workItemTypes, record);
|
|
||||||
recordsNotMatching = GetWorkItemsNotMatching122514(record, records);
|
|
||||||
if (!string.IsNullOrEmpty(record.WorkItem.Tags) && recordsNotMatching.Count == 0)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
collection.Add($"## {record.WorkItem.AssignedTo} - {record.WorkItem.Id} - {record.WorkItem.Title}");
|
|
||||||
collection.Add(string.Empty);
|
|
||||||
foreach (Record r in recordsNotMatching)
|
|
||||||
collection.Add($"- [ ] [{r.WorkItem}]({url}{r.WorkItem}) {nameof(record.WorkItem.Tags)} != {record.WorkItem.Tags}");
|
|
||||||
collection.Add(string.Empty);
|
|
||||||
lines.AddRange(collection);
|
|
||||||
violations.Add($"Tag:{record.WorkItem.Tags};");
|
|
||||||
foreach (Record r in recordsNotMatching)
|
|
||||||
violations.Add($"<a target='_blank' href='{url}{r.WorkItem.Id}'>{r.WorkItem.Id}</a>:{r.WorkItem.Tags};");
|
|
||||||
results.Add(Record.GetWithoutNesting(record, string.Join(" ", violations)));
|
|
||||||
}
|
|
||||||
return new(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ReadOnlyCollection<Record> GetWorkItemsNotMatching126169(Record record, ReadOnlyCollection<Record> records)
|
|
||||||
{
|
|
||||||
List<Record> results = new();
|
|
||||||
foreach (Record r in records)
|
|
||||||
{
|
|
||||||
if (record.WorkItem.Priority is null)
|
|
||||||
{
|
|
||||||
results.Add(record);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (r.WorkItem.Priority == record.WorkItem.Priority.Value)
|
|
||||||
continue;
|
|
||||||
results.Add(r);
|
|
||||||
}
|
|
||||||
return new(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ReadOnlyCollection<Record> FeatureCheckPriority126169(string url, List<string> lines, ReadOnlyCollection<string> workItemTypes, ReadOnlyDictionary<int, Record> keyValuePairs, string workItemType)
|
|
||||||
{
|
|
||||||
List<Record> results = new();
|
|
||||||
Record record;
|
|
||||||
List<string> collection = new();
|
|
||||||
List<string> violations = new();
|
|
||||||
ReadOnlyCollection<Record> records;
|
|
||||||
ReadOnlyCollection<Record> recordsNotMatching;
|
|
||||||
foreach (KeyValuePair<int, Record> keyValuePair in keyValuePairs)
|
|
||||||
{
|
|
||||||
record = keyValuePair.Value;
|
|
||||||
if (record.WorkItem.State is "Removed")
|
|
||||||
continue;
|
|
||||||
if (record.WorkItem.WorkItemType != workItemType)
|
|
||||||
continue;
|
|
||||||
collection.Clear();
|
|
||||||
violations.Clear();
|
|
||||||
if (record.Children is null || record.Children.Length == 0)
|
|
||||||
continue;
|
|
||||||
records = FilterChildren(workItemTypes, record);
|
|
||||||
recordsNotMatching = GetWorkItemsNotMatching126169(record, records);
|
|
||||||
if (recordsNotMatching.Count == 0)
|
|
||||||
continue;
|
|
||||||
collection.Add($"## {record.WorkItem.AssignedTo} - {record.WorkItem.Id} - {record.WorkItem.Title}");
|
|
||||||
collection.Add(string.Empty);
|
|
||||||
collection.Add($"- [{record.WorkItem.Id}]({url}{record.WorkItem.Id})");
|
|
||||||
foreach (Record r in recordsNotMatching)
|
|
||||||
collection.Add($"- [ ] [{r.WorkItem.Id}]({url}{r.WorkItem.Id}) {nameof(record.WorkItem.Priority)} != {record.WorkItem.Priority}");
|
|
||||||
collection.Add(string.Empty);
|
|
||||||
lines.AddRange(collection);
|
|
||||||
violations.Add($"Priority:{record.WorkItem.Priority};");
|
|
||||||
foreach (Record r in recordsNotMatching)
|
|
||||||
violations.Add($"<a target='_blank' href='{url}{r.WorkItem.Id}'>{r.WorkItem.Id}</a>:{r.WorkItem.Priority};");
|
|
||||||
results.Add(Record.GetWithoutNesting(record, string.Join(" ", violations)));
|
|
||||||
}
|
|
||||||
return new(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ReadOnlyCollection<Record> GetWorkItemsNotMatching123066(Record record, ReadOnlyCollection<Record> records)
|
|
||||||
{
|
|
||||||
List<Record> results = new();
|
|
||||||
int check;
|
|
||||||
int state = GetState(record.WorkItem);
|
|
||||||
List<KeyValuePair<int, Record>> collection = new();
|
|
||||||
foreach (Record r in records)
|
|
||||||
{
|
|
||||||
if (r.WorkItem.State is "Removed")
|
|
||||||
continue;
|
|
||||||
check = GetState(r.WorkItem);
|
|
||||||
if (check == state)
|
|
||||||
continue;
|
|
||||||
collection.Add(new(check, r));
|
|
||||||
}
|
|
||||||
if (collection.Count > 0)
|
|
||||||
{
|
|
||||||
KeyValuePair<int, Record>[] notNewState = (from l in collection where l.Value.WorkItem.State != "New" select l).ToArray();
|
|
||||||
if (notNewState.Length == 0 && record.WorkItem.State is "New" or "Active")
|
|
||||||
collection.Clear();
|
|
||||||
else if (notNewState.Length > 0)
|
|
||||||
{
|
|
||||||
int minimum = notNewState.Min(l => l.Key);
|
|
||||||
if (minimum == state)
|
|
||||||
collection.Clear();
|
|
||||||
else if (minimum == 1 && record.WorkItem.State == "New")
|
|
||||||
collection.Clear();
|
|
||||||
else if (notNewState.Length > 0 && record.WorkItem.State == "Active")
|
|
||||||
collection.Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach (KeyValuePair<int, Record> keyValuePair in collection.OrderByDescending(l => l.Key))
|
|
||||||
results.Add(keyValuePair.Value);
|
|
||||||
return new(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ReadOnlyCollection<Record> GetWorkItemsNotMatching123067(Record record, ReadOnlyCollection<Record> records)
|
|
||||||
{
|
|
||||||
List<Record> results = new();
|
|
||||||
int check;
|
|
||||||
int state = GetState(record.WorkItem);
|
|
||||||
List<KeyValuePair<int, Record>> collection = new();
|
|
||||||
foreach (Record r in records)
|
|
||||||
{
|
|
||||||
if (r.WorkItem.State is "Removed")
|
|
||||||
continue;
|
|
||||||
check = GetState(r.WorkItem);
|
|
||||||
if (check == state)
|
|
||||||
continue;
|
|
||||||
collection.Add(new(check, r));
|
|
||||||
}
|
|
||||||
if (collection.Count > 0)
|
|
||||||
{
|
|
||||||
KeyValuePair<int, Record>[] notNewState = (from l in collection where l.Value.WorkItem.State != "New" select l).ToArray();
|
|
||||||
if (notNewState.Length == 0 && record.WorkItem.State is "New" or "Active")
|
|
||||||
collection.Clear();
|
|
||||||
else if (notNewState.Length > 0)
|
|
||||||
{
|
|
||||||
int minimum = notNewState.Min(l => l.Key);
|
|
||||||
if (minimum == state)
|
|
||||||
collection.Clear();
|
|
||||||
else if (minimum == 1 && record.WorkItem.State == "New")
|
|
||||||
collection.Clear();
|
|
||||||
else if (notNewState.Length > 0 && record.WorkItem.State == "Active")
|
|
||||||
collection.Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach (KeyValuePair<int, Record> keyValuePair in collection.OrderByDescending(l => l.Key))
|
|
||||||
results.Add(keyValuePair.Value);
|
|
||||||
return new(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ReadOnlyCollection<Record> GetWorkItemsNotMatching122517(Record record, ReadOnlyCollection<Record> records)
|
|
||||||
{
|
|
||||||
List<Record> results = new();
|
|
||||||
if (record.WorkItem.StartDate is null)
|
|
||||||
throw new Exception();
|
|
||||||
DateTime dateTime = record.WorkItem.StartDate.Value;
|
|
||||||
List<KeyValuePair<long, Record>> collection = new();
|
|
||||||
foreach (Record r in records)
|
|
||||||
{
|
|
||||||
if (r.WorkItem.State is "Removed")
|
|
||||||
continue;
|
|
||||||
if (r.WorkItem.ActivatedDate is null)
|
|
||||||
continue;
|
|
||||||
if (dateTime >= r.WorkItem.ActivatedDate.Value)
|
|
||||||
continue;
|
|
||||||
collection.Add(new(r.WorkItem.ActivatedDate.Value.Ticks, r));
|
|
||||||
}
|
|
||||||
foreach (KeyValuePair<long, Record> keyValuePair in collection.OrderBy(l => l.Key))
|
|
||||||
results.Add(keyValuePair.Value);
|
|
||||||
return new(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ReadOnlyCollection<Record> FeatureCheckState123066(string url, List<string> lines, ReadOnlyCollection<string> workItemTypes, ReadOnlyDictionary<int, Record> keyValuePairs, string workItemType)
|
|
||||||
{
|
|
||||||
List<Record> results = new();
|
|
||||||
Record record;
|
|
||||||
List<string> collection = new();
|
|
||||||
List<string> violations = new();
|
|
||||||
ReadOnlyCollection<Record> records;
|
|
||||||
ReadOnlyCollection<Record> recordsNotMatching;
|
|
||||||
foreach (KeyValuePair<int, Record> keyValuePair in keyValuePairs)
|
|
||||||
{
|
|
||||||
record = keyValuePair.Value;
|
|
||||||
if (record.WorkItem.State is "Removed")
|
|
||||||
continue;
|
|
||||||
if (record.WorkItem.WorkItemType != workItemType)
|
|
||||||
continue;
|
|
||||||
collection.Clear();
|
|
||||||
violations.Clear();
|
|
||||||
if (record.Children is null || record.Children.Length == 0)
|
|
||||||
continue;
|
|
||||||
records = FilterChildren(workItemTypes, record);
|
|
||||||
recordsNotMatching = GetWorkItemsNotMatching123066(record, records);
|
|
||||||
if (recordsNotMatching.Count == 0)
|
|
||||||
continue;
|
|
||||||
collection.Add($"## {record.WorkItem.AssignedTo} - {record.WorkItem.Id} - {record.WorkItem.Title}");
|
|
||||||
collection.Add(string.Empty);
|
|
||||||
collection.Add($"- [{record.WorkItem.Id}]({url}{record.WorkItem.Id})");
|
|
||||||
foreach (Record r in recordsNotMatching)
|
|
||||||
collection.Add($"- [ ] [{r.WorkItem.Id}]({url}{r.WorkItem.Id}) {nameof(record.WorkItem.State)} != {record.WorkItem.State}");
|
|
||||||
collection.Add(string.Empty);
|
|
||||||
lines.AddRange(collection);
|
|
||||||
violations.Add($"State:{record.WorkItem.State};");
|
|
||||||
foreach (Record r in recordsNotMatching)
|
|
||||||
violations.Add($"<a target='_blank' href='{url}{r.WorkItem.Id}'>{r.WorkItem.Id}</a>:{r.WorkItem.State};");
|
|
||||||
results.Add(Record.GetWithoutNesting(record, string.Join(" ", violations)));
|
|
||||||
}
|
|
||||||
return new(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ReadOnlyCollection<Record> FeatureCheckState123067(string url, List<string> lines, ReadOnlyCollection<string> workItemTypes, ReadOnlyDictionary<int, Record> keyValuePairs, string workItemType)
|
|
||||||
{
|
|
||||||
List<Record> results = new();
|
|
||||||
Record record;
|
|
||||||
List<string> collection = new();
|
|
||||||
List<string> violations = new();
|
|
||||||
ReadOnlyCollection<Record> records;
|
|
||||||
ReadOnlyCollection<Record> recordsNotMatching;
|
|
||||||
foreach (KeyValuePair<int, Record> keyValuePair in keyValuePairs)
|
|
||||||
{
|
|
||||||
record = keyValuePair.Value;
|
|
||||||
if (record.WorkItem.State is "Removed")
|
|
||||||
continue;
|
|
||||||
if (record.WorkItem.WorkItemType != workItemType)
|
|
||||||
continue;
|
|
||||||
collection.Clear();
|
|
||||||
violations.Clear();
|
|
||||||
if (record.Children is null || record.Children.Length == 0)
|
|
||||||
continue;
|
|
||||||
records = FilterChildren(workItemTypes, record);
|
|
||||||
recordsNotMatching = GetWorkItemsNotMatching123067(record, records);
|
|
||||||
if (recordsNotMatching.Count == 0)
|
|
||||||
continue;
|
|
||||||
collection.Add($"## {record.WorkItem.AssignedTo} - {record.WorkItem.Id} - {record.WorkItem.Title}");
|
|
||||||
collection.Add(string.Empty);
|
|
||||||
collection.Add($"- [{record.WorkItem.Id}]({url}{record.WorkItem.Id})");
|
|
||||||
foreach (Record r in recordsNotMatching)
|
|
||||||
collection.Add($"- [ ] [{r.WorkItem.Id}]({url}{r.WorkItem.Id}) {nameof(record.WorkItem.State)} != {record.WorkItem.State}");
|
|
||||||
collection.Add(string.Empty);
|
|
||||||
lines.AddRange(collection);
|
|
||||||
violations.Add($"State:{record.WorkItem.State};");
|
|
||||||
foreach (Record r in recordsNotMatching)
|
|
||||||
violations.Add($"<a target='_blank' href='{url}{r.WorkItem.Id}'>{r.WorkItem.Id}</a>:{r.WorkItem.State};");
|
|
||||||
results.Add(Record.GetWithoutNesting(record, string.Join(" ", violations)));
|
|
||||||
}
|
|
||||||
return new(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ReadOnlyCollection<Record> FeatureCheckStart122517(string url, List<string> lines, ReadOnlyCollection<string> workItemTypes, ReadOnlyDictionary<int, Record> keyValuePairs, string workItemType)
|
|
||||||
{
|
|
||||||
List<Record> results = new();
|
|
||||||
Record record;
|
|
||||||
List<string> collection = new();
|
|
||||||
List<string> violations = new();
|
|
||||||
ReadOnlyCollection<Record> records;
|
|
||||||
ReadOnlyCollection<Record> recordsNotMatching;
|
|
||||||
foreach (KeyValuePair<int, Record> keyValuePair in keyValuePairs)
|
|
||||||
{
|
|
||||||
record = keyValuePair.Value;
|
|
||||||
if (record.WorkItem.State is "Removed")
|
|
||||||
continue;
|
|
||||||
if (record.WorkItem.WorkItemType != workItemType)
|
|
||||||
continue;
|
|
||||||
collection.Clear();
|
|
||||||
violations.Clear();
|
|
||||||
if (record.Children is null || record.Children.Length == 0)
|
|
||||||
continue;
|
|
||||||
if (record.WorkItem.StartDate is null)
|
|
||||||
continue;
|
|
||||||
records = FilterChildren(workItemTypes, record);
|
|
||||||
recordsNotMatching = GetWorkItemsNotMatching122517(record, records);
|
|
||||||
if (recordsNotMatching.Count == 0)
|
|
||||||
continue;
|
|
||||||
collection.Add($"## {record.WorkItem.AssignedTo} - {record.WorkItem.Id} - {record.WorkItem.Title}");
|
|
||||||
collection.Add(string.Empty);
|
|
||||||
collection.Add($"- [{record.WorkItem.Id}]({url}{record.WorkItem.Id})");
|
|
||||||
foreach (Record r in recordsNotMatching)
|
|
||||||
collection.Add($"- [ ] [{r.WorkItem.Id}]({url}{r.WorkItem.Id}) {nameof(record.WorkItem.ActivatedDate)} != {record.WorkItem.ActivatedDate}");
|
|
||||||
collection.Add(string.Empty);
|
|
||||||
lines.AddRange(collection);
|
|
||||||
violations.Add($"StartDate:{record.WorkItem.StartDate};");
|
|
||||||
foreach (Record r in recordsNotMatching)
|
|
||||||
violations.Add($"<a target='_blank' href='{url}{r.WorkItem.Id}'>{r.WorkItem.Id}</a>:{r.WorkItem.ActivatedDate};");
|
|
||||||
results.Add(Record.GetWithoutNesting(record, string.Join(" ", violations)));
|
|
||||||
}
|
|
||||||
return new(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ReadOnlyDictionary<string, List<Record>> GetWorkItemsMatching228385(ReadOnlyCollection<Record> records)
|
|
||||||
{
|
|
||||||
Dictionary<string, List<Record>> results = new();
|
|
||||||
string key;
|
|
||||||
List<Record>? collection;
|
|
||||||
foreach (Record record in records)
|
|
||||||
{
|
|
||||||
key = $"{record.WorkItem.IterationPath}-{record.WorkItem.AssignedTo}";
|
|
||||||
if (!results.TryGetValue(key, out collection))
|
|
||||||
{
|
|
||||||
results.Add(key, new());
|
|
||||||
if (!results.TryGetValue(key, out collection))
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
collection.Add(record);
|
|
||||||
}
|
|
||||||
return new(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ReadOnlyDictionary<string, List<Record>> GetWorkItemsMatching228385(ReadOnlyDictionary<int, Record> keyValuePairs, string workItemType)
|
|
||||||
{
|
|
||||||
ReadOnlyDictionary<string, List<Record>> results;
|
|
||||||
Record record;
|
|
||||||
List<Record> records = new();
|
|
||||||
foreach (KeyValuePair<int, Record> keyValuePair in keyValuePairs)
|
|
||||||
{
|
|
||||||
record = keyValuePair.Value;
|
|
||||||
if (record.WorkItem.State is "Removed" or "Closed")
|
|
||||||
continue;
|
|
||||||
if (!record.WorkItem.IterationPath.Contains('\\'))
|
|
||||||
continue;
|
|
||||||
if (record.WorkItem.StoryPoints is null)
|
|
||||||
continue;
|
|
||||||
if (record.WorkItem.WorkItemType != workItemType)
|
|
||||||
continue;
|
|
||||||
records.Add(record);
|
|
||||||
}
|
|
||||||
Record[] sorted = records.OrderByDescending(l => l.WorkItem.IterationPath).ToArray();
|
|
||||||
results = GetWorkItemsMatching228385(new(sorted));
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ReadOnlyCollection<Record> UserStoryCheckIterationPath228385(string url, List<string> lines, ReadOnlyCollection<string> _, ReadOnlyDictionary<int, Record> keyValuePairs, string workItemType)
|
|
||||||
{
|
|
||||||
List<Record> results = new();
|
|
||||||
long totalStoryPoints;
|
|
||||||
ReadOnlyDictionary<string, List<Record>> records = GetWorkItemsMatching228385(keyValuePairs, workItemType);
|
|
||||||
foreach (KeyValuePair<string, List<Record>> keyValuePair in records)
|
|
||||||
{
|
|
||||||
totalStoryPoints = 0;
|
|
||||||
foreach (Record record in keyValuePair.Value)
|
|
||||||
{
|
|
||||||
if (record.WorkItem.StoryPoints is null)
|
|
||||||
continue;
|
|
||||||
totalStoryPoints += record.WorkItem.StoryPoints.Value;
|
|
||||||
}
|
|
||||||
lines.Add(string.Empty);
|
|
||||||
lines.Add($"## {keyValuePair.Key} => {totalStoryPoints}");
|
|
||||||
lines.Add(string.Empty);
|
|
||||||
foreach (Record record in keyValuePair.Value)
|
|
||||||
lines.Add($"- [ ] [{record.WorkItem.Id}]({url}{record.WorkItem.Id}) - {record.WorkItem.Title}");
|
|
||||||
}
|
|
||||||
return new(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -5,16 +5,68 @@ using Adaptation.Shared.Duplicator;
|
|||||||
using Adaptation.Shared.Methods;
|
using Adaptation.Shared.Methods;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Adaptation.FileHandlers.MoveMatchingFiles;
|
namespace Adaptation.FileHandlers.MoveMatchingFiles;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
public class FileRead : Shared.FileRead, IFileRead
|
public class FileRead : Shared.FileRead, IFileRead
|
||||||
{
|
{
|
||||||
|
|
||||||
|
internal class PreWith
|
||||||
|
{
|
||||||
|
|
||||||
|
internal string MatchingFile { get; private set; }
|
||||||
|
internal string CheckFile { get; private set; }
|
||||||
|
internal string ErrFile { get; private set; }
|
||||||
|
internal string CheckDirectory { get; private set; }
|
||||||
|
internal string NoWaitDirectory { get; private set; }
|
||||||
|
|
||||||
|
internal PreWith(string matchingFile, string checkFile, string errFile, string checkDirectory, string noWaitDirectory)
|
||||||
|
{
|
||||||
|
MatchingFile = matchingFile;
|
||||||
|
CheckFile = checkFile;
|
||||||
|
ErrFile = errFile;
|
||||||
|
CheckDirectory = checkDirectory;
|
||||||
|
NoWaitDirectory = noWaitDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class Pre
|
||||||
|
{
|
||||||
|
|
||||||
|
internal string MatchingFile { get; private set; }
|
||||||
|
internal string CheckFile { get; private set; }
|
||||||
|
|
||||||
|
internal Pre(string matchingFile, string checkFile)
|
||||||
|
{
|
||||||
|
MatchingFile = matchingFile;
|
||||||
|
CheckFile = checkFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class Post
|
||||||
|
{
|
||||||
|
|
||||||
|
internal string ErrFile { get; private set; }
|
||||||
|
internal string CheckFile { get; private set; }
|
||||||
|
|
||||||
|
internal Post(string checkFile, string errFile)
|
||||||
|
{
|
||||||
|
ErrFile = errFile;
|
||||||
|
CheckFile = checkFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<string>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted) :
|
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<string>> 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)
|
base(new Description(), false, smtp, fileParameter, cellInstanceName, connectionCount, cellInstanceConnectionName, fileConnectorConfiguration, equipmentTypeName, parameterizedModelObjectDefinitionType, modelObjectParameters, equipmentDictionaryName, dummyRuns, staticRuns, useCyclicalForDescription, isEAFHosted: connectionCount is null)
|
||||||
{
|
{
|
||||||
@ -41,7 +93,8 @@ public class FileRead : Shared.FileRead, IFileRead
|
|||||||
Move(extractResults);
|
Move(extractResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFileRead.WaitForThread() => WaitForThread(thread: null, threadExceptions: null);
|
void IFileRead.WaitForThread() =>
|
||||||
|
WaitForThread(thread: null, threadExceptions: null);
|
||||||
|
|
||||||
string IFileRead.GetEventDescription()
|
string IFileRead.GetEventDescription()
|
||||||
{
|
{
|
||||||
@ -88,7 +141,7 @@ public class FileRead : Shared.FileRead, IFileRead
|
|||||||
DateTime dateTime = DateTime.Now;
|
DateTime dateTime = DateTime.Now;
|
||||||
results = GetExtractResult(reportFullPath, dateTime);
|
results = GetExtractResult(reportFullPath, dateTime);
|
||||||
if (results.Item3 is null)
|
if (results.Item3 is null)
|
||||||
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(results.Item1, Array.Empty<Test>(), JsonSerializer.Deserialize<JsonElement[]>("[]"), results.Item4);
|
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(results.Item1, Array.Empty<Test>(), JsonSerializer.Deserialize<JsonElement[]>("[]") ?? throw new Exception(), results.Item4);
|
||||||
if (results.Item3.Length > 0 && _IsEAFHosted)
|
if (results.Item3.Length > 0 && _IsEAFHosted)
|
||||||
WritePDSF(this, results.Item3);
|
WritePDSF(this, results.Item3);
|
||||||
UpdateLastTicksDuration(DateTime.Now.Ticks - dateTime.Ticks);
|
UpdateLastTicksDuration(DateTime.Now.Ticks - dateTime.Ticks);
|
||||||
@ -104,7 +157,69 @@ public class FileRead : Shared.FileRead, IFileRead
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<string> GetSearchDirectories(int numberLength, string parentDirectory)
|
private static ProcessDataStandardFormatMapping GetProcessDataStandardFormatMapping()
|
||||||
|
{
|
||||||
|
ProcessDataStandardFormatMapping result;
|
||||||
|
string[] segmentsB;
|
||||||
|
List<string> distinct = new();
|
||||||
|
Dictionary<string, string> keyValuePairs = new();
|
||||||
|
string args4 = "Time,Test,Count,MesEntity,HeaderUniqueId,UniqueId,Id,Recipe,Date,AreaDeltaFromLastRun,GLimit,HGCV1";
|
||||||
|
string args5 = "Nine10mmEdgeMean,Nine4mmEdgeMean,NineCriticalPointsAverage,NineCriticalPointsPhaseAngleAverage,NineCriticalPointsStdDev,NineEdgeMeanDelta,NineMean,NineResRangePercent,AreaDeltaFromLastRun,Variation,Percentage HgCV 4PP Delta,HGCV1";
|
||||||
|
string args6 = "RhoAvg01,RhoAvg02,RhoAvg03,RhoAvg04,RhoAvg05,RhoAvg06,RhoAvg07,RhoAvg08,RhoAvg09,HGCV1";
|
||||||
|
string args7 = "FlatZMean|MeanFlatZ,GradeMean|MeanGrade,NAvgMean|MeanNAvg,NslMean|MeanNsl,PhaseMean|MeanPhase,RhoAvgMean|MeanRhoAvg,RhoslMean|MeanRhosl,RsMean|MeanRs,VdMean|MeanVd,FlatZRadialGradient|RadialGradientFlatZ,GradeRadialGradient|RadialGradientGrade,NAvgRadialGradient|RadialGradientNAvg,NslRadialGradient|RadialGradientNsl,PhaseRadialGradient|RadialGradientPhase,RhoAvgRadialGradient|RadialGradientRhoAvg,RhoslRadialGradient|RadialGradientRhosl,RsRadialGradient|RadialGradientRs,VdRadialGradient|RadialGradientVd,FlatZStdDev|StandardDeviationPercentageFlatZ,GradeStdDev|StandardDeviationPercentageGrade,NAvgStdDev|StandardDeviationPercentageNAvg,NslStdDev|StandardDeviationPercentageNsl,PhaseStdDev|StandardDeviationPercentagePhase,RhoAvgStdDev|StandardDeviationPercentageRhoAvg,RhoslStdDev|StandardDeviationPercentageRhosl,RsStdDev|StandardDeviationPercentageRs,VdStdDev|StandardDeviationPercentageVd,|HGCV1";
|
||||||
|
string args8 = "Time,A_LOGISTICS,B_LOGISTICS,Test,Count,Index,MesEntity,Date,Employee,Lot,PSN,Reactor,Recipe,Area,Folder,HeaderUniqueId,Id,Layer,Model,Pattern,Phase,Plan,RampRate,RDS,SetupFile,StartVoltage,StopVoltage,UniqueId,Wafer,WaferSize,Zone,Ccomp,CondType,FlatZ,FlatZMean,FlatZRadialGradient,FlatZStdDev,GLimit,Grade,GradeMean,GradeRadialGradient,GradeStdDev,NAvg,NAvgMean,NAvgRadialGradient,NAvgStdDev,Nsl,NslMean,NslRadialGradient,NslStdDev,PhaseMean,PhaseRadialGradient,PhaseStdDev,RhoAvg,RhoAvgMean,RhoAvgRadialGradient,RhoAvgStdDev,RhoMethod,Rhosl,RhoslMean,RhoslRadialGradient,RhoslStdDev,RsMean,RsRadialGradient,RsStdDev,Vd,VdMean,VdRadialGradient,VdStdDev,Variation,AreaDeltaFromLastRun,Nine10mmEdgeMean,Nine4mmEdgeMean,NineCriticalPointsAverage,NineCriticalPointsPhaseAngleAverage,NineCriticalPointsStdDev,NineEdgeMeanDelta,NineMean,NineResRangePercent,RhoAvg01,RhoAvg02,RhoAvg03,RhoAvg04,RhoAvg05,RhoAvg06,RhoAvg07,RhoAvg08,RhoAvg09";
|
||||||
|
string args9 = "Time,A_LOGISTICS,B_LOGISTICS,Index,Operator,StartVoltage,Wafer,StopVoltage,Lot,RampRate,Plan,GLimit,Date,Time,SetupFile,WaferSize,Folder,Ccomp,Pattern,Area,CondType,RhoMethod,Model,MeanNAvg,MeanNsl,MeanVd,MeanFlatZ,MeanRhoAvg,MeanRhosl,MeanPhase,MeanGrade,MeanRs,StandardDeviationPercentageNAvg,StandardDeviationPercentageNsl,StandardDeviationPercentageVd,StandardDeviationPercentageFlatZ,StandardDeviationPercentageRhoAvg,StandardDeviationPercentageRhosl,StandardDeviationPercentagePhase,StandardDeviationPercentageGrade,StandardDeviationPercentageRs,RadialGradientNAvg,RadialGradientNsl,RadialGradientVd,RadialGradientFlatZ,RadialGradientRhoAvg,RadialGradientRhosl,RadialGradientPhase,RadialGradientGrade,RadialGradientRs,Site,X,Y,NAvg,RhoAvg,Nsl,Rhosl,Vd,Phase,FlatZ,Grade,XLeft,XRight,BottomY,TopY,RDS,PSN,Reactor,Layer,Zone,Employee,InferredLot,Nine10mmEdgeMean,Nine4mmEdgeMean,NineCriticalPointsAverage,NineCriticalPointsPhaseAngleAverage,NineCriticalPointsStdDev,NineEdgeMeanDelta,NineMean,NineResRangePercent,AreaDeltaFromLastRun,Variation,Percentage HgCV 4PP Delta,RhoAvg01,RhoAvg02,RhoAvg03,RhoAvg04,RhoAvg05,RhoAvg06,RhoAvg07,RhoAvg08,RhoAvg09";
|
||||||
|
string args10 = "0,1,2,-1,-1,3,-1,12,70,8,66,67,-1,19,16,-1,-1,68,22,18,58,10,9,65,14,5,7,-1,6,15,69,17,20,59,26,44,35,11,60,30,48,39,53,23,41,32,55,24,42,33,29,47,38,54,27,45,36,21,56,28,46,37,31,49,40,57,25,43,34,81,80,72,73,74,75,76,77,78,79,83,84,85,86,87,88,89,90,91";
|
||||||
|
string[] segments = args7.Split(',');
|
||||||
|
ReadOnlyCollection<string> ignoreColumns = new(args4.Split(','));
|
||||||
|
ReadOnlyCollection<string> newColumnNames = new(args9.Split(','));
|
||||||
|
ReadOnlyCollection<string> oldColumnNames = new(args8.Split(','));
|
||||||
|
ReadOnlyCollection<string> backfillColumns = new(args5.Split(','));
|
||||||
|
ReadOnlyCollection<string> indexOnlyColumns = new(args6.Split(','));
|
||||||
|
ReadOnlyCollection<int> columnIndices = new(args10.Split(',').Select(int.Parse).ToArray());
|
||||||
|
foreach (string segment in segments)
|
||||||
|
{
|
||||||
|
segmentsB = segment.Split('|');
|
||||||
|
if (segmentsB.Length != 2)
|
||||||
|
continue;
|
||||||
|
if (distinct.Contains(segmentsB[0]))
|
||||||
|
continue;
|
||||||
|
distinct.Add(segmentsB[0]);
|
||||||
|
keyValuePairs.Add(segmentsB[0], segmentsB[1]);
|
||||||
|
}
|
||||||
|
result = new(backfillColumns: backfillColumns,
|
||||||
|
columnIndices: columnIndices,
|
||||||
|
newColumnNames: newColumnNames,
|
||||||
|
ignoreColumns: ignoreColumns,
|
||||||
|
indexOnlyColumns: indexOnlyColumns,
|
||||||
|
keyValuePairs: new(keyValuePairs),
|
||||||
|
oldColumnNames: oldColumnNames);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyCollection<PreWith> GetPreWithCollection(ReadOnlyCollection<Pre> preCollection)
|
||||||
|
{
|
||||||
|
List<PreWith> results = new();
|
||||||
|
string errFile;
|
||||||
|
PreWith preWith;
|
||||||
|
string? checkDirectory;
|
||||||
|
string noWaitDirectory;
|
||||||
|
foreach (Pre pre in preCollection)
|
||||||
|
{
|
||||||
|
errFile = string.Concat(pre.CheckFile, ".err");
|
||||||
|
checkDirectory = Path.GetDirectoryName(pre.CheckFile);
|
||||||
|
if (string.IsNullOrEmpty(checkDirectory))
|
||||||
|
continue;
|
||||||
|
if (!Directory.Exists(checkDirectory))
|
||||||
|
_ = Directory.CreateDirectory(checkDirectory);
|
||||||
|
noWaitDirectory = Path.Combine(checkDirectory, "NoWaitDirectory");
|
||||||
|
preWith = new(pre.MatchingFile, pre.CheckFile, errFile, checkDirectory, noWaitDirectory);
|
||||||
|
results.Add(preWith);
|
||||||
|
}
|
||||||
|
return results.AsReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyCollection<string> GetSearchDirectories(int numberLength, string parentDirectory)
|
||||||
{
|
{
|
||||||
List<string> results = new();
|
List<string> results = new();
|
||||||
string[] directories = Directory.GetDirectories(parentDirectory, "*", SearchOption.TopDirectoryOnly);
|
string[] directories = Directory.GetDirectories(parentDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||||
@ -115,10 +230,137 @@ public class FileRead : Shared.FileRead, IFileRead
|
|||||||
results.Add(directory);
|
results.Add(directory);
|
||||||
}
|
}
|
||||||
results.Sort();
|
results.Sort();
|
||||||
|
return results.AsReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreatePointerFile(int numberLength, string parentDirectory, ReadOnlyCollection<string> matchingFiles)
|
||||||
|
{
|
||||||
|
string checkFile;
|
||||||
|
string writeFile;
|
||||||
|
string? directoryName;
|
||||||
|
int parentDirectoryLength = parentDirectory.Length;
|
||||||
|
foreach (string matchingFile in matchingFiles)
|
||||||
|
{
|
||||||
|
directoryName = Path.GetDirectoryName(matchingFile);
|
||||||
|
if (directoryName is null)
|
||||||
|
continue;
|
||||||
|
checkFile = $"{matchingFile[0]}{directoryName.Substring(parentDirectoryLength + numberLength + 1)}";
|
||||||
|
writeFile = Path.Combine(parentDirectory, $"{directoryName.Substring(parentDirectory.Length + 1, numberLength)}.txt");
|
||||||
|
if (File.Exists(writeFile))
|
||||||
|
continue;
|
||||||
|
File.AppendAllLines(writeFile, new string[] { parentDirectory, matchingFile, directoryName, checkFile });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyCollection<Pre> GetPreCollection(int numberLength, string parentDirectory, ReadOnlyCollection<string> matchingFiles)
|
||||||
|
{
|
||||||
|
List<Pre> results = new();
|
||||||
|
Pre pre;
|
||||||
|
string checkFile;
|
||||||
|
int parentDirectoryLength = parentDirectory.Length;
|
||||||
|
foreach (string matchingFile in matchingFiles)
|
||||||
|
{
|
||||||
|
checkFile = $"{matchingFile[0]}{matchingFile.Substring(parentDirectoryLength + numberLength + 1)}";
|
||||||
|
pre = new(matchingFile, checkFile);
|
||||||
|
results.Add(pre);
|
||||||
|
}
|
||||||
|
return results.AsReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MoveCollection(DateTime dateTime, ProcessDataStandardFormat? processDataStandardFormat, ReadOnlyCollection<PreWith> preWithCollection)
|
||||||
|
{
|
||||||
|
ReadOnlyCollection<Post> postCollection = GetPostCollection(dateTime, processDataStandardFormat, preWithCollection);
|
||||||
|
if (postCollection.Count != 0)
|
||||||
|
{
|
||||||
|
Thread.Sleep(500);
|
||||||
|
StringBuilder stringBuilder = new();
|
||||||
|
foreach (Post post in postCollection)
|
||||||
|
{
|
||||||
|
if (File.Exists(post.ErrFile))
|
||||||
|
_ = stringBuilder.AppendLine(File.ReadAllText(post.ErrFile));
|
||||||
|
if (File.Exists(post.CheckFile))
|
||||||
|
_ = stringBuilder.AppendLine($"<{post.CheckFile}> was not consumed by the end!");
|
||||||
|
}
|
||||||
|
if (stringBuilder.Length > 0)
|
||||||
|
throw new Exception(stringBuilder.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ReadOnlyCollection<Post> GetPostCollection(DateTime dateTime, ProcessDataStandardFormat? processDataStandardFormat, ReadOnlyCollection<PreWith> preWithCollection)
|
||||||
|
{
|
||||||
|
List<Post> results = new();
|
||||||
|
Post post;
|
||||||
|
long preWait;
|
||||||
|
foreach (PreWith preWith in preWithCollection)
|
||||||
|
{
|
||||||
|
if (processDataStandardFormat is null)
|
||||||
|
File.Move(preWith.MatchingFile, preWith.CheckFile);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ProcessDataStandardFormat.Write(preWith.CheckFile, processDataStandardFormat);
|
||||||
|
File.Delete(preWith.MatchingFile);
|
||||||
|
}
|
||||||
|
if (Directory.Exists(preWith.NoWaitDirectory))
|
||||||
|
{
|
||||||
|
post = new(preWith.CheckFile, preWith.ErrFile);
|
||||||
|
results.Add(post);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (_FileConnectorConfiguration?.FileHandleWaitTime is null)
|
||||||
|
preWait = DateTime.Now.AddMilliseconds(1234).Ticks;
|
||||||
|
else
|
||||||
|
preWait = DateTime.Now.AddMilliseconds(_FileConnectorConfiguration.FileHandleWaitTime.Value).Ticks;
|
||||||
|
for (short i = 0; i < short.MaxValue; i++)
|
||||||
|
{
|
||||||
|
if (DateTime.Now.Ticks > preWait)
|
||||||
|
break;
|
||||||
|
Thread.Sleep(500);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < int.MaxValue; i++)
|
||||||
|
{
|
||||||
|
if (File.Exists(preWith.ErrFile))
|
||||||
|
throw new Exception(File.ReadAllText(preWith.ErrFile));
|
||||||
|
if (!File.Exists(preWith.CheckFile))
|
||||||
|
break;
|
||||||
|
if (new TimeSpan(DateTime.Now.Ticks - dateTime.Ticks).TotalSeconds > _BreakAfterSeconds)
|
||||||
|
throw new Exception($"Not all files were consumed after {_BreakAfterSeconds} second(s)!");
|
||||||
|
Thread.Sleep(500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results.AsReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
|
||||||
|
{
|
||||||
|
Tuple<string, Test[], JsonElement[], List<FileInfo>> results = new(string.Empty, Array.Empty<Test>(), Array.Empty<JsonElement>(), new List<FileInfo>());
|
||||||
|
ProcessDataStandardFormatMapping processDataStandardFormatMapping = GetProcessDataStandardFormatMapping();
|
||||||
|
ProcessDataStandardFormat? processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath, processDataStandardFormatMapping);
|
||||||
|
if (processDataStandardFormat is not null)
|
||||||
|
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
|
||||||
|
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
|
||||||
|
processDataStandardFormat = null;
|
||||||
|
}
|
||||||
|
SetFileParameterLotIDToLogisticsMID();
|
||||||
|
int numberLength = 2;
|
||||||
|
long ticks = dateTime.Ticks;
|
||||||
|
string parentParentDirectory = GetParentParent(reportFullPath);
|
||||||
|
ReadOnlyCollection<string> searchDirectories = GetSearchDirectories(numberLength, parentParentDirectory);
|
||||||
|
ReadOnlyCollection<string> matchingFiles = GetMatchingFiles(ticks, reportFullPath, searchDirectories);
|
||||||
|
if (matchingFiles.Count != searchDirectories.Count)
|
||||||
|
throw new Exception($"Didn't find all files after {_BreakAfterSeconds} second(s)!");
|
||||||
|
try
|
||||||
|
{ CreatePointerFile(numberLength, parentParentDirectory, matchingFiles); }
|
||||||
|
catch (Exception) { }
|
||||||
|
ReadOnlyCollection<Pre> preCollection = GetPreCollection(numberLength, parentParentDirectory, matchingFiles);
|
||||||
|
ReadOnlyCollection<PreWith> preWithCollection = GetPreWithCollection(preCollection);
|
||||||
|
MoveCollection(dateTime, processDataStandardFormat, preWithCollection);
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<string> GetMatchingFiles(long ticks, string reportFullPath, List<string> searchDirectories)
|
private ReadOnlyCollection<string> GetMatchingFiles(long ticks, string reportFullPath, ReadOnlyCollection<string> searchDirectories)
|
||||||
{
|
{
|
||||||
List<string> results = new();
|
List<string> results = new();
|
||||||
string[] found;
|
string[] found;
|
||||||
@ -137,129 +379,7 @@ public class FileRead : Shared.FileRead, IFileRead
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return results;
|
return results.AsReadOnly();
|
||||||
}
|
|
||||||
|
|
||||||
private static List<(string matchingFile, string checkFile)> GetCollection(int numberLength, string parentDirectory, List<string> matchingFiles)
|
|
||||||
{
|
|
||||||
List<(string matchingFile, string checkFile)> results = new();
|
|
||||||
string checkFile;
|
|
||||||
int parentDirectoryLength = parentDirectory.Length;
|
|
||||||
foreach (string matchingFile in matchingFiles)
|
|
||||||
{
|
|
||||||
checkFile = $"{matchingFile[0]}{matchingFile.Substring(parentDirectoryLength + numberLength + 1)}";
|
|
||||||
results.Add(new(matchingFile, checkFile));
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<(string, string, string, string, string)> GetCollection(List<(string matchingFile, string checkFile)> collection)
|
|
||||||
{
|
|
||||||
List<(string, string, string, string, string)> results = new();
|
|
||||||
string errFile;
|
|
||||||
string checkDirectory;
|
|
||||||
string noWaitDirectory;
|
|
||||||
foreach ((string matchingFile, string checkFile) in collection)
|
|
||||||
{
|
|
||||||
errFile = string.Concat(checkFile, ".err");
|
|
||||||
checkDirectory = Path.GetDirectoryName(checkFile);
|
|
||||||
if (!Directory.Exists(checkDirectory))
|
|
||||||
_ = Directory.CreateDirectory(checkDirectory);
|
|
||||||
noWaitDirectory = Path.Combine(checkDirectory, "NoWaitDirectory");
|
|
||||||
results.Add(new(matchingFile, checkFile, errFile, checkDirectory, noWaitDirectory));
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void MoveCollection(DateTime dateTime, List<(string matchingFile, string checkFile)> collection)
|
|
||||||
{
|
|
||||||
long preWait;
|
|
||||||
List<(string checkFile, string errFile)> postCollection = new();
|
|
||||||
foreach ((string matchingFile, string checkFile, string errFile, string checkDirectory, string noWaitDirectory) in GetCollection(collection))
|
|
||||||
{
|
|
||||||
File.Move(matchingFile, checkFile);
|
|
||||||
if (Directory.Exists(noWaitDirectory))
|
|
||||||
{
|
|
||||||
postCollection.Add(new(checkFile, errFile));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (_FileConnectorConfiguration?.FileHandleWaitTime is null)
|
|
||||||
preWait = DateTime.Now.AddMilliseconds(1234).Ticks;
|
|
||||||
else
|
|
||||||
preWait = DateTime.Now.AddMilliseconds(_FileConnectorConfiguration.FileHandleWaitTime.Value).Ticks;
|
|
||||||
for (short i = 0; i < short.MaxValue; i++)
|
|
||||||
{
|
|
||||||
if (DateTime.Now.Ticks > preWait)
|
|
||||||
break;
|
|
||||||
Thread.Sleep(500);
|
|
||||||
}
|
|
||||||
for (int i = 0; i < int.MaxValue; i++)
|
|
||||||
{
|
|
||||||
if (File.Exists(errFile))
|
|
||||||
throw new Exception(File.ReadAllText(errFile));
|
|
||||||
if (!File.Exists(checkFile))
|
|
||||||
break;
|
|
||||||
if (new TimeSpan(DateTime.Now.Ticks - dateTime.Ticks).TotalSeconds > _BreakAfterSeconds)
|
|
||||||
throw new Exception($"Not all files were consumed after {_BreakAfterSeconds} second(s)!");
|
|
||||||
Thread.Sleep(500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (postCollection.Count != 0)
|
|
||||||
{
|
|
||||||
Thread.Sleep(500);
|
|
||||||
StringBuilder stringBuilder = new();
|
|
||||||
foreach ((string checkFile, string errFile) in postCollection)
|
|
||||||
{
|
|
||||||
if (File.Exists(errFile))
|
|
||||||
_ = stringBuilder.AppendLine(File.ReadAllText(errFile));
|
|
||||||
if (File.Exists(checkFile))
|
|
||||||
_ = stringBuilder.AppendLine($"<{checkFile}> was not consumed by the end!");
|
|
||||||
}
|
|
||||||
if (stringBuilder.Length > 0)
|
|
||||||
throw new Exception(stringBuilder.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void CreatePointerFile(int numberLength, string parentDirectory, List<string> matchingFiles)
|
|
||||||
{
|
|
||||||
#nullable enable
|
|
||||||
string checkFile;
|
|
||||||
string writeFile;
|
|
||||||
string? directoryName;
|
|
||||||
int parentDirectoryLength = parentDirectory.Length;
|
|
||||||
foreach (string matchingFile in matchingFiles)
|
|
||||||
{
|
|
||||||
directoryName = Path.GetDirectoryName(matchingFile);
|
|
||||||
if (directoryName is null)
|
|
||||||
continue;
|
|
||||||
checkFile = $"{matchingFile[0]}{directoryName.Substring(parentDirectoryLength + numberLength + 1)}";
|
|
||||||
writeFile = Path.Combine(parentDirectory, $"{directoryName.Substring(parentDirectory.Length + 1, numberLength)}.txt");
|
|
||||||
if (File.Exists(writeFile))
|
|
||||||
continue;
|
|
||||||
File.AppendAllLines(writeFile, new string[] { parentDirectory, matchingFile, directoryName, checkFile });
|
|
||||||
}
|
|
||||||
#nullable disable
|
|
||||||
}
|
|
||||||
|
|
||||||
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
|
|
||||||
{
|
|
||||||
Tuple<string, Test[], JsonElement[], List<FileInfo>> results = new(string.Empty, null, null, new List<FileInfo>());
|
|
||||||
ProcessData processData = ProcessDataStandardFormat.GetProcessData(reportFullPath);
|
|
||||||
_Logistics = new Logistics(reportFullPath, processData.Logistics);
|
|
||||||
SetFileParameterLotIDToLogisticsMID();
|
|
||||||
int numberLength = 2;
|
|
||||||
long ticks = dateTime.Ticks;
|
|
||||||
string parentParentDirectory = GetParentParent(reportFullPath);
|
|
||||||
List<string> searchDirectories = GetSearchDirectories(numberLength, parentParentDirectory);
|
|
||||||
List<string> matchingFiles = GetMatchingFiles(ticks, reportFullPath, searchDirectories);
|
|
||||||
if (matchingFiles.Count != searchDirectories.Count)
|
|
||||||
throw new Exception($"Didn't find all files after {_BreakAfterSeconds} second(s)!");
|
|
||||||
try
|
|
||||||
{ CreatePointerFile(numberLength, parentParentDirectory, matchingFiles); }
|
|
||||||
catch (Exception) { }
|
|
||||||
List<(string matchingFile, string checkFile)> collection = GetCollection(numberLength, parentParentDirectory, matchingFiles);
|
|
||||||
MoveCollection(dateTime, collection);
|
|
||||||
return results;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -118,15 +118,15 @@ public class FileRead : Shared.FileRead, IFileRead
|
|||||||
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
|
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
|
||||||
{
|
{
|
||||||
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
|
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
|
||||||
ProcessData processData = ProcessDataStandardFormat.GetProcessData(reportFullPath);
|
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
|
||||||
_Logistics = new Logistics(reportFullPath, processData.Logistics);
|
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
|
||||||
SetFileParameterLotIDToLogisticsMID();
|
SetFileParameterLotIDToLogisticsMID();
|
||||||
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processData);
|
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
|
||||||
List<Description> descriptions = json.ProcessData.GetDescriptions(jsonElements);
|
List<Description> descriptions = json.ProcessData.GetDescriptions(jsonElements);
|
||||||
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
|
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
|
||||||
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
|
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
|
||||||
SaveOpenInsightFile(reportFullPath, dateTime, descriptions, tests);
|
SaveOpenInsightFile(reportFullPath, dateTime, descriptions, tests);
|
||||||
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(processData.Logistics, tests, jsonElements, new List<FileInfo>());
|
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List<FileInfo>());
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,15 +129,15 @@ public class FileRead : Shared.FileRead, IFileRead
|
|||||||
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
|
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
|
||||||
{
|
{
|
||||||
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
|
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
|
||||||
ProcessData processData = ProcessDataStandardFormat.GetProcessData(reportFullPath);
|
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
|
||||||
_Logistics = new Logistics(reportFullPath, processData.Logistics);
|
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
|
||||||
SetFileParameterLotIDToLogisticsMID();
|
SetFileParameterLotIDToLogisticsMID();
|
||||||
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processData);
|
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
|
||||||
List<Description> descriptions = json.ProcessData.GetDescriptions(jsonElements);
|
List<Description> descriptions = json.ProcessData.GetDescriptions(jsonElements);
|
||||||
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
|
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
|
||||||
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
|
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
|
||||||
SendData(reportFullPath, dateTime, descriptions);
|
SendData(reportFullPath, dateTime, descriptions);
|
||||||
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(processData.Logistics, tests, jsonElements, new List<FileInfo>());
|
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List<FileInfo>());
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,15 +146,15 @@ public class FileRead : Shared.FileRead, IFileRead
|
|||||||
if (dateTime == DateTime.MinValue)
|
if (dateTime == DateTime.MinValue)
|
||||||
throw new ArgumentNullException(nameof(dateTime));
|
throw new ArgumentNullException(nameof(dateTime));
|
||||||
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
|
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
|
||||||
ProcessData processData = ProcessDataStandardFormat.GetProcessData(reportFullPath);
|
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
|
||||||
_Logistics = new Logistics(reportFullPath, processData.Logistics);
|
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
|
||||||
SetFileParameterLotIDToLogisticsMID();
|
SetFileParameterLotIDToLogisticsMID();
|
||||||
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processData);
|
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
|
||||||
List<Description> descriptions = json.ProcessData.GetDescriptions(jsonElements);
|
List<Description> descriptions = json.ProcessData.GetDescriptions(jsonElements);
|
||||||
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
|
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
|
||||||
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
|
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
|
||||||
PostOpenInsightMetrologyViewerAttachments(descriptions);
|
PostOpenInsightMetrologyViewerAttachments(descriptions);
|
||||||
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(processData.Logistics, tests, jsonElements, new List<FileInfo>());
|
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List<FileInfo>());
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +131,9 @@ public class FileRead : Shared.FileRead, IFileRead
|
|||||||
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
|
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
|
||||||
if (dateTime == DateTime.MinValue)
|
if (dateTime == DateTime.MinValue)
|
||||||
throw new ArgumentNullException(nameof(dateTime));
|
throw new ArgumentNullException(nameof(dateTime));
|
||||||
_Logistics = new Logistics(reportFullPath, $"LOGISTICS_1{'\t'}A_JOBID={"BACKLOG"};A_MES_ENTITY={"BACKLOG"};");
|
string[] lines = new string[] { string.Empty, "NUM_DATA_ROWS", $"LOGISTICS_1{'\t'}A_JOBID={"BACKLOG"};A_MES_ENTITY={"BACKLOG"};" };
|
||||||
|
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath, lines);
|
||||||
|
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
|
||||||
results = new(_Logistics.Logistics1[0], Array.Empty<Test>(), Array.Empty<JsonElement>(), new List<FileInfo>());
|
results = new(_Logistics.Logistics1[0], Array.Empty<Test>(), Array.Empty<JsonElement>(), new List<FileInfo>());
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
@ -143,13 +143,13 @@ public class FileRead : Shared.FileRead, IFileRead
|
|||||||
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
|
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
|
||||||
{
|
{
|
||||||
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
|
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
|
||||||
ProcessData processData = ProcessDataStandardFormat.GetProcessData(reportFullPath);
|
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
|
||||||
_Logistics = new Logistics(reportFullPath, processData.Logistics);
|
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
|
||||||
SetFileParameterLotIDToLogisticsMID();
|
SetFileParameterLotIDToLogisticsMID();
|
||||||
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processData);
|
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
|
||||||
List<Description> descriptions = json.ProcessData.GetDescriptions(jsonElements);
|
List<Description> descriptions = json.ProcessData.GetDescriptions(jsonElements);
|
||||||
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
|
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
|
||||||
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(processData.Logistics, tests, jsonElements, new List<FileInfo>());
|
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List<FileInfo>());
|
||||||
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
|
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
|
||||||
DirectoryMove(reportFullPath, dateTime, descriptions);
|
DirectoryMove(reportFullPath, dateTime, descriptions);
|
||||||
else if (!_IsEAFHosted)
|
else if (!_IsEAFHosted)
|
||||||
|
@ -117,15 +117,15 @@ public class FileRead : Shared.FileRead, IFileRead
|
|||||||
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
|
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
|
||||||
{
|
{
|
||||||
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
|
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
|
||||||
ProcessData processData = ProcessDataStandardFormat.GetProcessData(reportFullPath);
|
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
|
||||||
_Logistics = new Logistics(reportFullPath, processData.Logistics);
|
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
|
||||||
SetFileParameterLotIDToLogisticsMID();
|
SetFileParameterLotIDToLogisticsMID();
|
||||||
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processData);
|
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
|
||||||
List<Shared.Properties.IDescription> descriptions = GetDuplicatorDescriptions(jsonElements);
|
List<Shared.Properties.IDescription> descriptions = GetDuplicatorDescriptions(jsonElements);
|
||||||
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
|
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
|
||||||
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
|
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
|
||||||
FileCopy(reportFullPath, dateTime, descriptions);
|
FileCopy(reportFullPath, dateTime, descriptions);
|
||||||
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(processData.Logistics, tests, jsonElements, new List<FileInfo>());
|
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List<FileInfo>());
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
127
Adaptation/FileHandlers/Violation/FileRead.cs
Normal file
127
Adaptation/FileHandlers/Violation/FileRead.cs
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
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.IO;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace Adaptation.FileHandlers.Violation;
|
||||||
|
|
||||||
|
public class FileRead : Shared.FileRead, IFileRead
|
||||||
|
{
|
||||||
|
|
||||||
|
private long? _TickOffset;
|
||||||
|
private readonly string _URL;
|
||||||
|
private readonly ReadOnlyCollection<string> _WorkItemTypes;
|
||||||
|
|
||||||
|
public FileRead(ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<string>> 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 cellInstanceNamed = string.Concat("CellInstance.", _EquipmentType);
|
||||||
|
_URL = GetPropertyValue(cellInstanceConnectionName, modelObjectParameters, $"{cellInstanceNamed}.URL");
|
||||||
|
string workItemTypes = GetPropertyValue(cellInstanceConnectionName, modelObjectParameters, $"{cellInstanceNamed}.WorkItemTypes");
|
||||||
|
_WorkItemTypes = new(workItemTypes.Split('|'));
|
||||||
|
if (_IsEAFHosted)
|
||||||
|
NestExistingFiles(_FileConnectorConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IFileRead.Move(Tuple<string, Test[], JsonElement[], List<FileInfo>> extractResults, Exception exception) => Move(extractResults);
|
||||||
|
|
||||||
|
void IFileRead.WaitForThread() => WaitForThread(thread: null, threadExceptions: null);
|
||||||
|
|
||||||
|
string IFileRead.GetEventDescription()
|
||||||
|
{
|
||||||
|
string result = _Description.GetEventDescription();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<string> IFileRead.GetHeaderNames()
|
||||||
|
{
|
||||||
|
List<string> results = _Description.GetHeaderNames();
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
string[] IFileRead.Move(Tuple<string, Test[], JsonElement[], List<FileInfo>> 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<string, string> IFileRead.GetDisplayNamesJsonElement()
|
||||||
|
{
|
||||||
|
Dictionary<string, string> results = _Description.GetDisplayNamesJsonElement(this);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<IDescription> IFileRead.GetDescriptions(IFileRead fileRead, List<Test> tests, IProcessData processData)
|
||||||
|
{
|
||||||
|
List<IDescription> results = _Description.GetDescriptions(fileRead, _Logistics, tests, processData);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tuple<string, Test[], JsonElement[], List<FileInfo>> IFileRead.GetExtractResult(string reportFullPath, string eventName)
|
||||||
|
{
|
||||||
|
Tuple<string, Test[], JsonElement[], List<FileInfo>> 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<string, Test[], JsonElement[], List<FileInfo>>(results.Item1, Array.Empty<Test>(), JsonSerializer.Deserialize<JsonElement[]>("[]"), results.Item4);
|
||||||
|
if (results.Item3.Length > 0 && _IsEAFHosted)
|
||||||
|
WritePDSF(this, results.Item3);
|
||||||
|
UpdateLastTicksDuration(DateTime.Now.Ticks - dateTime.Ticks);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tuple<string, Test[], JsonElement[], List<FileInfo>> IFileRead.ReExtract()
|
||||||
|
{
|
||||||
|
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
|
||||||
|
List<string> headerNames = _Description.GetHeaderNames();
|
||||||
|
Dictionary<string, string> keyValuePairs = _Description.GetDisplayNamesJsonElement(this);
|
||||||
|
results = ReExtract(this, headerNames, keyValuePairs);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
|
||||||
|
{
|
||||||
|
Tuple<string, Test[], JsonElement[], List<FileInfo>> results = new(string.Empty, null, null, new List<FileInfo>());
|
||||||
|
_TickOffset ??= 0; // new FileInfo(reportFullPath).LastWriteTime.Ticks - dateTime.Ticks;
|
||||||
|
string[] lines = new string[] { string.Empty, "NUM_DATA_ROWS", $"LOGISTICS_1{'\t'}A_JOBID={"BACKLOG"};A_MES_ENTITY={"BACKLOG"};" };
|
||||||
|
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath, lines);
|
||||||
|
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
|
||||||
|
SetFileParameterLotIDToLogisticsMID();
|
||||||
|
if (_Logistics.FileInfo.Length < _MinFileLength)
|
||||||
|
results.Item4.Add(_Logistics.FileInfo);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IProcessData iProcessData = new ProcessData(this, _Logistics, _FileConnectorConfiguration.TargetFileLocation, _URL, _WorkItemTypes, results.Item4);
|
||||||
|
if (iProcessData.Details.Count == 0)
|
||||||
|
results = new(string.Concat("B) No Data - ", dateTime.Ticks), Array.Empty<Test>(), Array.Empty<JsonElement>(), results.Item4);
|
||||||
|
else
|
||||||
|
results = iProcessData.GetResults(this, _Logistics, results.Item4);
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
706
Adaptation/FileHandlers/Violation/ProcessData.cs
Normal file
706
Adaptation/FileHandlers/Violation/ProcessData.cs
Normal file
@ -0,0 +1,706 @@
|
|||||||
|
using Adaptation.FileHandlers.json.WorkItems;
|
||||||
|
using Adaptation.Shared;
|
||||||
|
using Adaptation.Shared.Duplicator;
|
||||||
|
using Adaptation.Shared.Methods;
|
||||||
|
using log4net;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Adaptation.FileHandlers.Violation;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
public class ProcessData : IProcessData
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly List<object> _Details;
|
||||||
|
|
||||||
|
List<object> Shared.Properties.IProcessData.Details => _Details;
|
||||||
|
|
||||||
|
private readonly ILog _Log;
|
||||||
|
|
||||||
|
string IProcessData.GetCurrentReactor(IFileRead fileRead, Logistics logistics, Dictionary<string, string> reactors) =>
|
||||||
|
throw new Exception(string.Concat("See ", nameof(WriteFiles)));
|
||||||
|
|
||||||
|
Tuple<string, Test[], JsonElement[], List<FileInfo>> IProcessData.GetResults(IFileRead fileRead, Logistics logistics, List<FileInfo> fileInfoCollection) =>
|
||||||
|
new(logistics.Logistics1[0], Array.Empty<Test>(), Array.Empty<JsonElement>(), fileInfoCollection);
|
||||||
|
|
||||||
|
public ProcessData(IFileRead fileRead, Logistics logistics, string targetFileLocation, string url, ReadOnlyCollection<string> workItemTypes, List<FileInfo> fileInfoCollection)
|
||||||
|
{
|
||||||
|
if (fileRead.IsEAFHosted)
|
||||||
|
{ }
|
||||||
|
_Details = new List<object>();
|
||||||
|
_Log = LogManager.GetLogger(typeof(ProcessData));
|
||||||
|
WriteFiles(fileRead, logistics, targetFileLocation, url, fileInfoCollection, workItemTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteFiles(IFileRead fileRead, Logistics logistics, string destinationDirectory, string url, List<FileInfo> fileInfoCollection, ReadOnlyCollection<string> __)
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(destinationDirectory))
|
||||||
|
_ = Directory.CreateDirectory(destinationDirectory);
|
||||||
|
string json = File.ReadAllText(logistics.ReportFullPath);
|
||||||
|
// WorkItem[]? workItems = JsonSerializer.Deserialize<WorkItem[]>(json);
|
||||||
|
// if (workItems is null)
|
||||||
|
// throw new Exception(nameof(workItems));
|
||||||
|
JsonElement[]? jsonElements = JsonSerializer.Deserialize<JsonElement[]>(json);
|
||||||
|
if (jsonElements is null)
|
||||||
|
throw new Exception(nameof(jsonElements));
|
||||||
|
WorkItem? workItem;
|
||||||
|
List<WorkItem> workItems = new();
|
||||||
|
foreach (JsonElement jsonElement in jsonElements)
|
||||||
|
{
|
||||||
|
workItem = JsonSerializer.Deserialize<WorkItem>(jsonElement.ToString());
|
||||||
|
if (workItem is null)
|
||||||
|
continue;
|
||||||
|
workItems.Add(workItem);
|
||||||
|
}
|
||||||
|
List<char> spaces = new();
|
||||||
|
bool keepRelations = false;
|
||||||
|
List<string> lines = new();
|
||||||
|
List<string> messages = new();
|
||||||
|
ReadOnlyCollection<Record> results;
|
||||||
|
ReadOnlyDictionary<int, Record> keyValuePairs = GetWorkItems(workItems, keepRelations);
|
||||||
|
ReadOnlyCollection<Record> records = new(keyValuePairs.Values.ToArray());
|
||||||
|
ReadOnlyCollection<string> userStoryWorkItemTypes = new(new string[] { "User Story" });
|
||||||
|
ReadOnlyCollection<string> bugFeatureWorkItemTypes = new(new string[] { "Bug", "Feature" });
|
||||||
|
ReadOnlyCollection<string> bugUserStoryWorkItemTypes = new(new string[] { "Bug", "User Story" });
|
||||||
|
ReadOnlyCollection<string> bugUserStoryTaskWorkItemTypes = new(new string[] { "Bug", "User Story", "Task" });
|
||||||
|
{
|
||||||
|
lines.Clear();
|
||||||
|
string workItemType = "Feature";
|
||||||
|
lines.Add($"# {nameof(FeatureCheckIterationPath122508)}");
|
||||||
|
lines.Add(string.Empty);
|
||||||
|
results = FeatureCheckIterationPath122508(url, lines, bugUserStoryTaskWorkItemTypes, keyValuePairs, workItemType);
|
||||||
|
WriteFiles(fileRead, destinationDirectory, fileInfoCollection, new(lines), workItemType, results, "check-122508");
|
||||||
|
_Details.Add(results);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
lines.Clear();
|
||||||
|
string workItemType = "Feature";
|
||||||
|
lines.Add($"# {nameof(FeatureCheckTag122514)}");
|
||||||
|
lines.Add(string.Empty);
|
||||||
|
results = FeatureCheckTag122514(url, lines, bugUserStoryWorkItemTypes, keyValuePairs, workItemType);
|
||||||
|
WriteFiles(fileRead, destinationDirectory, fileInfoCollection, new(lines), workItemType, results, "check-122514");
|
||||||
|
_Details.Add(results);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
lines.Clear();
|
||||||
|
string workItemType = "Feature";
|
||||||
|
lines.Add($"# {nameof(FeatureCheckPriority126169)}");
|
||||||
|
lines.Add(string.Empty);
|
||||||
|
results = FeatureCheckPriority126169(url, lines, bugUserStoryWorkItemTypes, keyValuePairs, workItemType);
|
||||||
|
WriteFiles(fileRead, destinationDirectory, fileInfoCollection, new(lines), workItemType, results, "check-126169");
|
||||||
|
_Details.Add(results);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
lines.Clear();
|
||||||
|
string workItemType = "Feature";
|
||||||
|
lines.Add($"# {nameof(FeatureCheckState123066)}");
|
||||||
|
lines.Add(string.Empty);
|
||||||
|
results = FeatureCheckState123066(url, lines, bugUserStoryTaskWorkItemTypes, keyValuePairs, workItemType);
|
||||||
|
WriteFiles(fileRead, destinationDirectory, fileInfoCollection, new(lines), workItemType, results, "check-123066");
|
||||||
|
_Details.Add(results);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
lines.Clear();
|
||||||
|
string workItemType = "Feature";
|
||||||
|
lines.Add($"# {nameof(FeatureCheckState123067)}");
|
||||||
|
lines.Add(string.Empty);
|
||||||
|
results = FeatureCheckState123067(url, lines, bugUserStoryTaskWorkItemTypes, keyValuePairs, workItemType);
|
||||||
|
WriteFiles(fileRead, destinationDirectory, fileInfoCollection, new(lines), workItemType, results, "check-123067");
|
||||||
|
_Details.Add(results);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
lines.Clear();
|
||||||
|
string workItemType = "Feature";
|
||||||
|
lines.Add($"# {nameof(FeatureCheckStart122517)}");
|
||||||
|
lines.Add(string.Empty);
|
||||||
|
results = FeatureCheckStart122517(url, lines, bugUserStoryTaskWorkItemTypes, keyValuePairs, workItemType);
|
||||||
|
WriteFiles(fileRead, destinationDirectory, fileInfoCollection, new(lines), workItemType, results, "check-122517");
|
||||||
|
_Details.Add(results);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
lines.Clear();
|
||||||
|
string workItemType = "User Story";
|
||||||
|
lines.Add($"# {nameof(UserStoryCheckIterationPath228385)}");
|
||||||
|
lines.Add(string.Empty);
|
||||||
|
results = UserStoryCheckIterationPath228385(url, lines, userStoryWorkItemTypes, keyValuePairs, workItemType);
|
||||||
|
WriteFiles(fileRead, destinationDirectory, fileInfoCollection, new(lines), workItemType, results, "check-228385");
|
||||||
|
_Details.Add(results);
|
||||||
|
}
|
||||||
|
if (messages.Count > 0)
|
||||||
|
throw new Exception($"{messages.Count}{Environment.NewLine}{string.Join(Environment.NewLine, messages)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyDictionary<int, Record> GetWorkItems(IEnumerable<WorkItem> workItems, bool keepRelations)
|
||||||
|
{
|
||||||
|
ReadOnlyDictionary<int, Record> results;
|
||||||
|
Dictionary<int, WorkItem> keyValuePairs = new();
|
||||||
|
foreach (WorkItem workItem in workItems)
|
||||||
|
keyValuePairs.Add(workItem.Id, workItem);
|
||||||
|
results = GetKeyValuePairs(new(keyValuePairs), keepRelations);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyDictionary<int, Record> GetKeyValuePairs(ReadOnlyDictionary<int, WorkItem> keyValuePairs, bool keepRelations)
|
||||||
|
{
|
||||||
|
Dictionary<int, Record> results = new();
|
||||||
|
Record record;
|
||||||
|
List<bool> nests = new();
|
||||||
|
WorkItem? parentWorkItem;
|
||||||
|
ReadOnlyCollection<Record> childRecords;
|
||||||
|
ReadOnlyCollection<Record> relatedRecords;
|
||||||
|
ReadOnlyCollection<Record> successorRecords;
|
||||||
|
foreach (KeyValuePair<int, WorkItem> keyValuePair in keyValuePairs)
|
||||||
|
{
|
||||||
|
nests.Clear();
|
||||||
|
if (keyValuePair.Value.Parent is null)
|
||||||
|
parentWorkItem = null;
|
||||||
|
else
|
||||||
|
_ = keyValuePairs.TryGetValue(keyValuePair.Value.Parent.Value, out parentWorkItem);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
childRecords = Record.GetKeyValuePairs(keyValuePairs, keyValuePair.Value, "Child", nests, keepRelations); // Forward
|
||||||
|
relatedRecords = Record.GetKeyValuePairs(keyValuePairs, keyValuePair.Value, "Related", nests, keepRelations); // Related
|
||||||
|
successorRecords = Record.GetKeyValuePairs(keyValuePairs, keyValuePair.Value, "Successor", nests, keepRelations); // Forward
|
||||||
|
// predecessorRecords = Record.GetKeyValuePairs(keyValuePairs, keyValuePair.Value, "Predecessor", nests, keepRelations); // Reverse
|
||||||
|
record = Record.Get(keyValuePair.Value, parentWorkItem, childRecords, relatedRecords, successorRecords, keepRelations);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
record = new(keyValuePair.Value, parentWorkItem, Array.Empty<Record>(), Array.Empty<Record>(), Array.Empty<Record>());
|
||||||
|
}
|
||||||
|
results.Add(keyValuePair.Key, record);
|
||||||
|
}
|
||||||
|
return new(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyCollection<Record> FeatureCheckIterationPath122508(string url, List<string> lines, ReadOnlyCollection<string> workItemTypes, ReadOnlyDictionary<int, Record> keyValuePairs, string workItemType)
|
||||||
|
{
|
||||||
|
List<Record> results = new();
|
||||||
|
Record record;
|
||||||
|
List<string> violations = new();
|
||||||
|
List<string> collection = new();
|
||||||
|
ReadOnlyCollection<Record> records;
|
||||||
|
ReadOnlyCollection<Record> maxIterationPaths;
|
||||||
|
foreach (KeyValuePair<int, Record> keyValuePair in keyValuePairs)
|
||||||
|
{
|
||||||
|
record = keyValuePair.Value;
|
||||||
|
if (record.WorkItem.State is "Removed")
|
||||||
|
continue;
|
||||||
|
if (!record.WorkItem.IterationPath.Contains('\\'))
|
||||||
|
continue;
|
||||||
|
if (record.WorkItem.WorkItemType != workItemType)
|
||||||
|
continue;
|
||||||
|
collection.Clear();
|
||||||
|
violations.Clear();
|
||||||
|
if (record.Children is null || record.Children.Length == 0)
|
||||||
|
continue;
|
||||||
|
records = FilterChildren(workItemTypes, record);
|
||||||
|
maxIterationPaths = GetMaxIterationPaths122508(records);
|
||||||
|
foreach (Record r in maxIterationPaths)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(r.WorkItem.IterationPath) || record.WorkItem.IterationPath == r.WorkItem.IterationPath)
|
||||||
|
continue;
|
||||||
|
violations.Add($"<a target='_blank' href='{url}{r.WorkItem.Id}'>{r.WorkItem.Id}</a>:{r.WorkItem.IterationPath};");
|
||||||
|
}
|
||||||
|
if (violations.Count > 0)
|
||||||
|
{
|
||||||
|
collection.Insert(0, string.Empty);
|
||||||
|
collection.Insert(0, $"## {record.WorkItem.AssignedTo} - {record.WorkItem.Id} - {record.WorkItem.Title}");
|
||||||
|
lines.AddRange(collection);
|
||||||
|
violations.Insert(0, $"<a target='_blank' href='{url}{record.WorkItem.Id}'>IterationPath</a>:{record.WorkItem.IterationPath};");
|
||||||
|
results.Add(Record.GetWithoutNesting(record, string.Join(" ", violations)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyCollection<Record> GetMaxIterationPaths122508(ReadOnlyCollection<Record> records)
|
||||||
|
{
|
||||||
|
List<Record> results;
|
||||||
|
List<Record>? collection;
|
||||||
|
Dictionary<string, List<Record>> keyValuePairs = new();
|
||||||
|
foreach (Record record in records)
|
||||||
|
{
|
||||||
|
if (!keyValuePairs.TryGetValue(record.WorkItem.IterationPath, out collection))
|
||||||
|
{
|
||||||
|
keyValuePairs.Add(record.WorkItem.IterationPath, new());
|
||||||
|
if (!keyValuePairs.TryGetValue(record.WorkItem.IterationPath, out collection))
|
||||||
|
throw new Exception();
|
||||||
|
|
||||||
|
}
|
||||||
|
collection.Add(record);
|
||||||
|
}
|
||||||
|
string? max = keyValuePairs.Keys.Max();
|
||||||
|
results = string.IsNullOrEmpty(max) ? new() : keyValuePairs[max];
|
||||||
|
return results.AsReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteFiles(IFileRead fileRead, string destinationDirectory, List<FileInfo> fileInfoCollection, ReadOnlyCollection<string> lines, string _, ReadOnlyCollection<Record> records, string fileName)
|
||||||
|
{
|
||||||
|
string markdown = string.Join(Environment.NewLine, lines);
|
||||||
|
string markdownFile = Path.Combine(destinationDirectory, $"{fileName}.md");
|
||||||
|
string markdownOld = !File.Exists(markdownFile) ? string.Empty : File.ReadAllText(markdownFile);
|
||||||
|
if (markdown != markdownOld)
|
||||||
|
File.WriteAllText(markdownFile, markdown);
|
||||||
|
if (!fileRead.IsEAFHosted)
|
||||||
|
fileInfoCollection.Add(new(markdownFile));
|
||||||
|
string html = CommonMark.CommonMarkConverter.Convert(markdown).Replace("<a href", "<a target='_blank' href");
|
||||||
|
string htmlFile = Path.Combine(destinationDirectory, $"{fileName}.html");
|
||||||
|
string htmlOld = !File.Exists(htmlFile) ? string.Empty : File.ReadAllText(htmlFile);
|
||||||
|
if (html != htmlOld)
|
||||||
|
File.WriteAllText(htmlFile, html);
|
||||||
|
if (!fileRead.IsEAFHosted)
|
||||||
|
fileInfoCollection.Add(new(htmlFile));
|
||||||
|
string json = JsonSerializer.Serialize(records, new JsonSerializerOptions() { WriteIndented = true });
|
||||||
|
string jsonFile = Path.Combine(destinationDirectory, $"{fileName}.json");
|
||||||
|
string jsonOld = !File.Exists(jsonFile) ? string.Empty : File.ReadAllText(jsonFile);
|
||||||
|
if (json != jsonOld)
|
||||||
|
File.WriteAllText(jsonFile, json);
|
||||||
|
if (!fileRead.IsEAFHosted)
|
||||||
|
fileInfoCollection.Add(new(jsonFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyCollection<Record> FeatureCheckTag122514(string url, List<string> lines, ReadOnlyCollection<string> workItemTypes, ReadOnlyDictionary<int, Record> keyValuePairs, string workItemType)
|
||||||
|
{
|
||||||
|
List<Record> results = new();
|
||||||
|
Record record;
|
||||||
|
List<string> collection = new();
|
||||||
|
List<string> violations = new();
|
||||||
|
ReadOnlyCollection<Record> records;
|
||||||
|
ReadOnlyCollection<Record> recordsNotMatching;
|
||||||
|
foreach (KeyValuePair<int, Record> keyValuePair in keyValuePairs)
|
||||||
|
{
|
||||||
|
record = keyValuePair.Value;
|
||||||
|
if (record.WorkItem.State is "Removed")
|
||||||
|
continue;
|
||||||
|
if (record.WorkItem.WorkItemType != workItemType)
|
||||||
|
continue;
|
||||||
|
collection.Clear();
|
||||||
|
violations.Clear();
|
||||||
|
if (record.Children is null || record.Children.Length == 0)
|
||||||
|
continue;
|
||||||
|
if (string.IsNullOrEmpty(record.WorkItem.Tags))
|
||||||
|
recordsNotMatching = new(new Record[] { record });
|
||||||
|
else
|
||||||
|
{
|
||||||
|
records = FilterChildren(workItemTypes, record);
|
||||||
|
recordsNotMatching = GetWorkItemsNotMatching122514(record, records);
|
||||||
|
if (!string.IsNullOrEmpty(record.WorkItem.Tags) && recordsNotMatching.Count == 0)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
collection.Add($"## {record.WorkItem.AssignedTo} - {record.WorkItem.Id} - {record.WorkItem.Title}");
|
||||||
|
collection.Add(string.Empty);
|
||||||
|
foreach (Record r in recordsNotMatching)
|
||||||
|
collection.Add($"- [ ] [{r.WorkItem}]({url}{r.WorkItem}) {nameof(record.WorkItem.Tags)} != {record.WorkItem.Tags}");
|
||||||
|
collection.Add(string.Empty);
|
||||||
|
lines.AddRange(collection);
|
||||||
|
violations.Add($"<a target='_blank' href='{url}{record.WorkItem.Id}'>Tag</a>:{record.WorkItem.Tags};");
|
||||||
|
foreach (Record r in recordsNotMatching)
|
||||||
|
violations.Add($"<a target='_blank' href='{url}{r.WorkItem.Id}'>{r.WorkItem.Id}</a>:{r.WorkItem.Tags};");
|
||||||
|
results.Add(Record.GetWithoutNesting(record, string.Join(" ", violations)));
|
||||||
|
}
|
||||||
|
return new(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyCollection<Record> FilterChildren(ReadOnlyCollection<string> workItemTypes, Record record)
|
||||||
|
{
|
||||||
|
List<Record> results = new();
|
||||||
|
FilterChildren(workItemTypes, record, results);
|
||||||
|
return new(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void FilterChildren(ReadOnlyCollection<string> workItemTypes, Record record, List<Record> results)
|
||||||
|
{
|
||||||
|
if (record.Children is not null)
|
||||||
|
{
|
||||||
|
foreach (Record r in record.Children)
|
||||||
|
{
|
||||||
|
if (!workItemTypes.Contains(r.WorkItem.WorkItemType))
|
||||||
|
continue;
|
||||||
|
results.Add(r);
|
||||||
|
FilterChildren(workItemTypes, r, results);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyCollection<Record> GetWorkItemsNotMatching122514(Record record, ReadOnlyCollection<Record> records)
|
||||||
|
{
|
||||||
|
List<Record> results = new();
|
||||||
|
string[] segments;
|
||||||
|
string[] parentTags = record.WorkItem.Tags.Split(';').Select(l => l.Trim()).ToArray();
|
||||||
|
foreach (Record r in records)
|
||||||
|
{
|
||||||
|
segments = string.IsNullOrEmpty(r.WorkItem.Tags) ? Array.Empty<string>() : r.WorkItem.Tags.Split(';').Select(l => l.Trim()).ToArray();
|
||||||
|
if (segments.Length > 0 && parentTags.Any(l => segments.Contains(l)))
|
||||||
|
continue;
|
||||||
|
results.Add(r);
|
||||||
|
}
|
||||||
|
return new(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyCollection<Record> FeatureCheckPriority126169(string url, List<string> lines, ReadOnlyCollection<string> workItemTypes, ReadOnlyDictionary<int, Record> keyValuePairs, string workItemType)
|
||||||
|
{
|
||||||
|
List<Record> results = new();
|
||||||
|
Record record;
|
||||||
|
List<string> collection = new();
|
||||||
|
List<string> violations = new();
|
||||||
|
ReadOnlyCollection<Record> records;
|
||||||
|
ReadOnlyCollection<Record> recordsNotMatching;
|
||||||
|
foreach (KeyValuePair<int, Record> keyValuePair in keyValuePairs)
|
||||||
|
{
|
||||||
|
record = keyValuePair.Value;
|
||||||
|
if (record.WorkItem.State is "Removed")
|
||||||
|
continue;
|
||||||
|
if (record.WorkItem.WorkItemType != workItemType)
|
||||||
|
continue;
|
||||||
|
collection.Clear();
|
||||||
|
violations.Clear();
|
||||||
|
if (record.Children is null || record.Children.Length == 0)
|
||||||
|
continue;
|
||||||
|
records = FilterChildren(workItemTypes, record);
|
||||||
|
recordsNotMatching = GetWorkItemsNotMatching126169(record, records);
|
||||||
|
if (recordsNotMatching.Count == 0)
|
||||||
|
continue;
|
||||||
|
collection.Add($"## {record.WorkItem.AssignedTo} - {record.WorkItem.Id} - {record.WorkItem.Title}");
|
||||||
|
collection.Add(string.Empty);
|
||||||
|
collection.Add($"- [{record.WorkItem.Id}]({url}{record.WorkItem.Id})");
|
||||||
|
foreach (Record r in recordsNotMatching)
|
||||||
|
collection.Add($"- [ ] [{r.WorkItem.Id}]({url}{r.WorkItem.Id}) {nameof(record.WorkItem.Priority)} != {record.WorkItem.Priority}");
|
||||||
|
collection.Add(string.Empty);
|
||||||
|
lines.AddRange(collection);
|
||||||
|
violations.Add($"<a target='_blank' href='{url}{record.WorkItem.Id}'>Priority</a>:{record.WorkItem.Priority};");
|
||||||
|
foreach (Record r in recordsNotMatching)
|
||||||
|
violations.Add($"<a target='_blank' href='{url}{r.WorkItem.Id}'>{r.WorkItem.Id}</a>:{r.WorkItem.Priority};");
|
||||||
|
results.Add(Record.GetWithoutNesting(record, string.Join(" ", violations)));
|
||||||
|
}
|
||||||
|
return new(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyCollection<Record> GetWorkItemsNotMatching126169(Record record, ReadOnlyCollection<Record> records)
|
||||||
|
{
|
||||||
|
List<Record> results = new();
|
||||||
|
foreach (Record r in records)
|
||||||
|
{
|
||||||
|
if (record.WorkItem.Priority is null)
|
||||||
|
{
|
||||||
|
results.Add(record);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (r.WorkItem.Priority == record.WorkItem.Priority.Value)
|
||||||
|
continue;
|
||||||
|
results.Add(r);
|
||||||
|
}
|
||||||
|
return new(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyCollection<Record> FeatureCheckState123066(string url, List<string> lines, ReadOnlyCollection<string> workItemTypes, ReadOnlyDictionary<int, Record> keyValuePairs, string workItemType)
|
||||||
|
{
|
||||||
|
List<Record> results = new();
|
||||||
|
Record record;
|
||||||
|
List<string> collection = new();
|
||||||
|
List<string> violations = new();
|
||||||
|
ReadOnlyCollection<Record> records;
|
||||||
|
ReadOnlyCollection<Record> recordsNotMatching;
|
||||||
|
foreach (KeyValuePair<int, Record> keyValuePair in keyValuePairs)
|
||||||
|
{
|
||||||
|
record = keyValuePair.Value;
|
||||||
|
if (record.WorkItem.State is "Removed")
|
||||||
|
continue;
|
||||||
|
if (record.WorkItem.WorkItemType != workItemType)
|
||||||
|
continue;
|
||||||
|
collection.Clear();
|
||||||
|
violations.Clear();
|
||||||
|
if (record.Children is null || record.Children.Length == 0)
|
||||||
|
continue;
|
||||||
|
records = FilterChildren(workItemTypes, record);
|
||||||
|
recordsNotMatching = GetWorkItemsNotMatching123066(record, records);
|
||||||
|
if (recordsNotMatching.Count == 0)
|
||||||
|
continue;
|
||||||
|
collection.Add($"## {record.WorkItem.AssignedTo} - {record.WorkItem.Id} - {record.WorkItem.Title}");
|
||||||
|
collection.Add(string.Empty);
|
||||||
|
collection.Add($"- [{record.WorkItem.Id}]({url}{record.WorkItem.Id})");
|
||||||
|
foreach (Record r in recordsNotMatching)
|
||||||
|
collection.Add($"- [ ] [{r.WorkItem.Id}]({url}{r.WorkItem.Id}) {nameof(record.WorkItem.State)} != {record.WorkItem.State}");
|
||||||
|
collection.Add(string.Empty);
|
||||||
|
lines.AddRange(collection);
|
||||||
|
violations.Add($"<a target='_blank' href='{url}{record.WorkItem.Id}'>State</a>:{record.WorkItem.State};");
|
||||||
|
foreach (Record r in recordsNotMatching)
|
||||||
|
violations.Add($"<a target='_blank' href='{url}{r.WorkItem.Id}'>{r.WorkItem.Id}</a>:{r.WorkItem.State};");
|
||||||
|
results.Add(Record.GetWithoutNesting(record, string.Join(" ", violations)));
|
||||||
|
}
|
||||||
|
return new(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyCollection<Record> GetWorkItemsNotMatching123066(Record record, ReadOnlyCollection<Record> records)
|
||||||
|
{
|
||||||
|
List<Record> results = new();
|
||||||
|
int check;
|
||||||
|
int state = GetState(record.WorkItem);
|
||||||
|
List<KeyValuePair<int, Record>> collection = new();
|
||||||
|
foreach (Record r in records)
|
||||||
|
{
|
||||||
|
if (r.WorkItem.State is "Removed")
|
||||||
|
continue;
|
||||||
|
check = GetState(r.WorkItem);
|
||||||
|
if (check == state)
|
||||||
|
continue;
|
||||||
|
collection.Add(new(check, r));
|
||||||
|
}
|
||||||
|
if (collection.Count > 0)
|
||||||
|
{
|
||||||
|
KeyValuePair<int, Record>[] notNewState = (from l in collection where l.Value.WorkItem.State != "New" select l).ToArray();
|
||||||
|
if (notNewState.Length == 0 && record.WorkItem.State is "New" or "Active")
|
||||||
|
collection.Clear();
|
||||||
|
else if (notNewState.Length > 0)
|
||||||
|
{
|
||||||
|
int minimum = notNewState.Min(l => l.Key);
|
||||||
|
if (minimum == state)
|
||||||
|
collection.Clear();
|
||||||
|
else if (minimum == 1 && record.WorkItem.State == "New")
|
||||||
|
collection.Clear();
|
||||||
|
else if (notNewState.Length > 0 && record.WorkItem.State == "Active")
|
||||||
|
collection.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (KeyValuePair<int, Record> keyValuePair in collection.OrderByDescending(l => l.Key))
|
||||||
|
results.Add(keyValuePair.Value);
|
||||||
|
return new(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetState(WorkItem workItem) =>
|
||||||
|
workItem.State switch
|
||||||
|
{
|
||||||
|
"New" => 1,
|
||||||
|
"Active" => 2,
|
||||||
|
"Resolved" => 3,
|
||||||
|
"Closed" => 4,
|
||||||
|
"Removed" => 5,
|
||||||
|
_ => 8
|
||||||
|
};
|
||||||
|
|
||||||
|
private static ReadOnlyCollection<Record> FeatureCheckState123067(string url, List<string> lines, ReadOnlyCollection<string> workItemTypes, ReadOnlyDictionary<int, Record> keyValuePairs, string workItemType)
|
||||||
|
{
|
||||||
|
List<Record> results = new();
|
||||||
|
Record record;
|
||||||
|
List<string> collection = new();
|
||||||
|
List<string> violations = new();
|
||||||
|
ReadOnlyCollection<Record> records;
|
||||||
|
ReadOnlyCollection<Record> recordsNotMatching;
|
||||||
|
foreach (KeyValuePair<int, Record> keyValuePair in keyValuePairs)
|
||||||
|
{
|
||||||
|
record = keyValuePair.Value;
|
||||||
|
if (record.WorkItem.State is "Removed")
|
||||||
|
continue;
|
||||||
|
if (record.WorkItem.WorkItemType != workItemType)
|
||||||
|
continue;
|
||||||
|
collection.Clear();
|
||||||
|
violations.Clear();
|
||||||
|
if (record.Children is null || record.Children.Length == 0)
|
||||||
|
continue;
|
||||||
|
records = FilterChildren(workItemTypes, record);
|
||||||
|
recordsNotMatching = GetWorkItemsNotMatching123067(record, records);
|
||||||
|
if (recordsNotMatching.Count == 0)
|
||||||
|
continue;
|
||||||
|
collection.Add($"## {record.WorkItem.AssignedTo} - {record.WorkItem.Id} - {record.WorkItem.Title}");
|
||||||
|
collection.Add(string.Empty);
|
||||||
|
collection.Add($"- [{record.WorkItem.Id}]({url}{record.WorkItem.Id})");
|
||||||
|
foreach (Record r in recordsNotMatching)
|
||||||
|
collection.Add($"- [ ] [{r.WorkItem.Id}]({url}{r.WorkItem.Id}) {nameof(record.WorkItem.State)} != {record.WorkItem.State}");
|
||||||
|
collection.Add(string.Empty);
|
||||||
|
lines.AddRange(collection);
|
||||||
|
violations.Add($"<a target='_blank' href='{url}{record.WorkItem.Id}'>State</a>:{record.WorkItem.State};");
|
||||||
|
foreach (Record r in recordsNotMatching)
|
||||||
|
violations.Add($"<a target='_blank' href='{url}{r.WorkItem.Id}'>{r.WorkItem.Id}</a>:{r.WorkItem.State};");
|
||||||
|
results.Add(Record.GetWithoutNesting(record, string.Join(" ", violations)));
|
||||||
|
}
|
||||||
|
return new(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyCollection<Record> GetWorkItemsNotMatching123067(Record record, ReadOnlyCollection<Record> records)
|
||||||
|
{
|
||||||
|
List<Record> results = new();
|
||||||
|
int check;
|
||||||
|
int state = GetState(record.WorkItem);
|
||||||
|
List<KeyValuePair<int, Record>> collection = new();
|
||||||
|
foreach (Record r in records)
|
||||||
|
{
|
||||||
|
if (r.WorkItem.State is "Removed")
|
||||||
|
continue;
|
||||||
|
check = GetState(r.WorkItem);
|
||||||
|
if (check == state)
|
||||||
|
continue;
|
||||||
|
collection.Add(new(check, r));
|
||||||
|
}
|
||||||
|
if (collection.Count > 0)
|
||||||
|
{
|
||||||
|
KeyValuePair<int, Record>[] notNewState = (from l in collection where l.Value.WorkItem.State != "New" select l).ToArray();
|
||||||
|
if (notNewState.Length == 0 && record.WorkItem.State is "New" or "Active")
|
||||||
|
collection.Clear();
|
||||||
|
else if (notNewState.Length > 0)
|
||||||
|
{
|
||||||
|
int minimum = notNewState.Min(l => l.Key);
|
||||||
|
if (minimum == state)
|
||||||
|
collection.Clear();
|
||||||
|
else if (minimum == 1 && record.WorkItem.State == "New")
|
||||||
|
collection.Clear();
|
||||||
|
else if (notNewState.Length > 0 && record.WorkItem.State == "Active")
|
||||||
|
collection.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (KeyValuePair<int, Record> keyValuePair in collection.OrderByDescending(l => l.Key))
|
||||||
|
results.Add(keyValuePair.Value);
|
||||||
|
return new(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyCollection<Record> FeatureCheckStart122517(string url, List<string> lines, ReadOnlyCollection<string> workItemTypes, ReadOnlyDictionary<int, Record> keyValuePairs, string workItemType)
|
||||||
|
{
|
||||||
|
List<Record> results = new();
|
||||||
|
Record record;
|
||||||
|
List<string> collection = new();
|
||||||
|
List<string> violations = new();
|
||||||
|
ReadOnlyCollection<Record> records;
|
||||||
|
ReadOnlyCollection<Record> recordsNotMatching;
|
||||||
|
foreach (KeyValuePair<int, Record> keyValuePair in keyValuePairs)
|
||||||
|
{
|
||||||
|
record = keyValuePair.Value;
|
||||||
|
if (record.WorkItem.State is "Removed")
|
||||||
|
continue;
|
||||||
|
if (record.WorkItem.WorkItemType != workItemType)
|
||||||
|
continue;
|
||||||
|
collection.Clear();
|
||||||
|
violations.Clear();
|
||||||
|
if (record.Children is null || record.Children.Length == 0)
|
||||||
|
continue;
|
||||||
|
if (record.WorkItem.StartDate is null)
|
||||||
|
continue;
|
||||||
|
records = FilterChildren(workItemTypes, record);
|
||||||
|
recordsNotMatching = GetWorkItemsNotMatching122517(record, records);
|
||||||
|
if (recordsNotMatching.Count == 0)
|
||||||
|
continue;
|
||||||
|
collection.Add($"## {record.WorkItem.AssignedTo} - {record.WorkItem.Id} - {record.WorkItem.Title}");
|
||||||
|
collection.Add(string.Empty);
|
||||||
|
collection.Add($"- [{record.WorkItem.Id}]({url}{record.WorkItem.Id})");
|
||||||
|
foreach (Record r in recordsNotMatching)
|
||||||
|
collection.Add($"- [ ] [{r.WorkItem.Id}]({url}{r.WorkItem.Id}) {nameof(record.WorkItem.ActivatedDate)} != {record.WorkItem.ActivatedDate}");
|
||||||
|
collection.Add(string.Empty);
|
||||||
|
lines.AddRange(collection);
|
||||||
|
violations.Add($"<a target='_blank' href='{url}{record.WorkItem.Id}'>StartDate</a>:{record.WorkItem.StartDate};");
|
||||||
|
foreach (Record r in recordsNotMatching)
|
||||||
|
violations.Add($"<a target='_blank' href='{url}{r.WorkItem.Id}'>{r.WorkItem.Id}</a>:{r.WorkItem.ActivatedDate};");
|
||||||
|
results.Add(Record.GetWithoutNesting(record, string.Join(" ", violations)));
|
||||||
|
}
|
||||||
|
return new(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyCollection<Record> GetWorkItemsNotMatching122517(Record record, ReadOnlyCollection<Record> records)
|
||||||
|
{
|
||||||
|
List<Record> results = new();
|
||||||
|
if (record.WorkItem.StartDate is null)
|
||||||
|
throw new Exception();
|
||||||
|
DateTime dateTime = record.WorkItem.StartDate.Value;
|
||||||
|
List<KeyValuePair<long, Record>> collection = new();
|
||||||
|
foreach (Record r in records)
|
||||||
|
{
|
||||||
|
if (r.WorkItem.State is "Removed")
|
||||||
|
continue;
|
||||||
|
if (r.WorkItem.ActivatedDate is null)
|
||||||
|
continue;
|
||||||
|
if (dateTime >= r.WorkItem.ActivatedDate.Value)
|
||||||
|
continue;
|
||||||
|
collection.Add(new(r.WorkItem.ActivatedDate.Value.Ticks, r));
|
||||||
|
}
|
||||||
|
foreach (KeyValuePair<long, Record> keyValuePair in collection.OrderBy(l => l.Key))
|
||||||
|
results.Add(keyValuePair.Value);
|
||||||
|
return new(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyCollection<Record> UserStoryCheckIterationPath228385(string url, List<string> lines, ReadOnlyCollection<string> _, ReadOnlyDictionary<int, Record> keyValuePairs, string workItemType)
|
||||||
|
{
|
||||||
|
List<Record> results = new();
|
||||||
|
long totalStoryPoints;
|
||||||
|
ReadOnlyDictionary<string, List<Record>> records = GetWorkItemsMatching228385(keyValuePairs, workItemType);
|
||||||
|
foreach (KeyValuePair<string, List<Record>> keyValuePair in records)
|
||||||
|
{
|
||||||
|
totalStoryPoints = 0;
|
||||||
|
foreach (Record record in keyValuePair.Value)
|
||||||
|
{
|
||||||
|
if (record.WorkItem.StoryPoints is null)
|
||||||
|
continue;
|
||||||
|
totalStoryPoints += record.WorkItem.StoryPoints.Value;
|
||||||
|
}
|
||||||
|
lines.Add(string.Empty);
|
||||||
|
lines.Add($"## {keyValuePair.Key} => {totalStoryPoints}");
|
||||||
|
lines.Add(string.Empty);
|
||||||
|
foreach (Record record in keyValuePair.Value)
|
||||||
|
lines.Add($"- [ ] [{record.WorkItem.Id}]({url}{record.WorkItem.Id}) - {record.WorkItem.Title}");
|
||||||
|
}
|
||||||
|
return new(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyDictionary<string, List<Record>> GetWorkItemsMatching228385(ReadOnlyDictionary<int, Record> keyValuePairs, string workItemType)
|
||||||
|
{
|
||||||
|
ReadOnlyDictionary<string, List<Record>> results;
|
||||||
|
Record record;
|
||||||
|
List<Record> records = new();
|
||||||
|
foreach (KeyValuePair<int, Record> keyValuePair in keyValuePairs)
|
||||||
|
{
|
||||||
|
record = keyValuePair.Value;
|
||||||
|
if (record.WorkItem.State is "Removed" or "Closed")
|
||||||
|
continue;
|
||||||
|
if (!record.WorkItem.IterationPath.Contains('\\'))
|
||||||
|
continue;
|
||||||
|
if (record.WorkItem.StoryPoints is null)
|
||||||
|
continue;
|
||||||
|
if (record.WorkItem.WorkItemType != workItemType)
|
||||||
|
continue;
|
||||||
|
records.Add(record);
|
||||||
|
}
|
||||||
|
Record[] sorted = records.OrderByDescending(l => l.WorkItem.IterationPath).ToArray();
|
||||||
|
results = GetWorkItemsMatching228385(new(sorted));
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyDictionary<string, List<Record>> GetWorkItemsMatching228385(ReadOnlyCollection<Record> records)
|
||||||
|
{
|
||||||
|
Dictionary<string, List<Record>> results = new();
|
||||||
|
string key;
|
||||||
|
List<Record>? collection;
|
||||||
|
foreach (Record record in records)
|
||||||
|
{
|
||||||
|
key = $"{record.WorkItem.IterationPath}-{record.WorkItem.AssignedTo}";
|
||||||
|
if (!results.TryGetValue(key, out collection))
|
||||||
|
{
|
||||||
|
results.Add(key, new());
|
||||||
|
if (!results.TryGetValue(key, out collection))
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
collection.Add(record);
|
||||||
|
}
|
||||||
|
return new(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static List<Description> GetDescriptions(JsonElement[] jsonElements)
|
||||||
|
{
|
||||||
|
List<Description> results = new();
|
||||||
|
Description? description;
|
||||||
|
JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString };
|
||||||
|
foreach (JsonElement jsonElement in jsonElements)
|
||||||
|
{
|
||||||
|
if (jsonElement.ValueKind != JsonValueKind.Object)
|
||||||
|
throw new Exception();
|
||||||
|
description = JsonSerializer.Deserialize<Description>(jsonElement.ToString(), jsonSerializerOptions);
|
||||||
|
if (description is null)
|
||||||
|
continue;
|
||||||
|
results.Add(description);
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -358,7 +358,9 @@ public class FileRead : Shared.FileRead, IFileRead
|
|||||||
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
|
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
|
||||||
{
|
{
|
||||||
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
|
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
|
||||||
_Logistics = new Logistics(reportFullPath, $"LOGISTICS_1{'\t'}A_JOBID={"BACKLOG"};A_MES_ENTITY={"BACKLOG"};");
|
string[] lines = new string[] { string.Empty, "NUM_DATA_ROWS", $"LOGISTICS_1{'\t'}A_JOBID={"BACKLOG"};A_MES_ENTITY={"BACKLOG"};" };
|
||||||
|
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath, lines);
|
||||||
|
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
|
||||||
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
|
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
|
||||||
MoveJson(reportFullPath, dateTime);
|
MoveJson(reportFullPath, dateTime);
|
||||||
results = new(_Logistics.Logistics1[0], Array.Empty<Test>(), Array.Empty<JsonElement>(), new List<FileInfo>());
|
results = new(_Logistics.Logistics1[0], Array.Empty<Test>(), Array.Empty<JsonElement>(), new List<FileInfo>());
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -35,6 +35,9 @@ public class Logistics : ILogistics
|
|||||||
public long Sequence => _Sequence;
|
public long Sequence => _Sequence;
|
||||||
public double TotalSecondsSinceLastWriteTimeFromSequence => _TotalSecondsSinceLastWriteTimeFromSequence;
|
public double TotalSecondsSinceLastWriteTimeFromSequence => _TotalSecondsSinceLastWriteTimeFromSequence;
|
||||||
|
|
||||||
|
private static string DefaultMesEntity(DateTime dateTime) =>
|
||||||
|
string.Concat(dateTime.Ticks, "_MES_ENTITY");
|
||||||
|
|
||||||
public Logistics(IFileRead fileRead)
|
public Logistics(IFileRead fileRead)
|
||||||
{
|
{
|
||||||
DateTime dateTime = DateTime.Now;
|
DateTime dateTime = DateTime.Now;
|
||||||
@ -84,13 +87,13 @@ public class Logistics : ILogistics
|
|||||||
_Logistics2 = new List<Logistics2>();
|
_Logistics2 = new List<Logistics2>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Logistics(string reportFullPath, string logistics)
|
internal Logistics(string reportFullPath, ProcessDataStandardFormat processDataStandardFormat)
|
||||||
{
|
{
|
||||||
string key;
|
string key;
|
||||||
DateTime dateTime;
|
DateTime dateTime;
|
||||||
string[] segments;
|
string[] segments;
|
||||||
_FileInfo = new(reportFullPath);
|
_FileInfo = new(reportFullPath);
|
||||||
_Logistics1 = logistics.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
_Logistics1 = processDataStandardFormat.Logistics.ToList();
|
||||||
if (Logistics1.Count == 0 || !Logistics1[0].StartsWith("LOGISTICS_1"))
|
if (Logistics1.Count == 0 || !Logistics1[0].StartsWith("LOGISTICS_1"))
|
||||||
{
|
{
|
||||||
_NullData = null;
|
_NullData = null;
|
||||||
@ -190,8 +193,6 @@ public class Logistics : ILogistics
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string DefaultMesEntity(DateTime dateTime) => string.Concat(dateTime.Ticks, "_MES_ENTITY");
|
|
||||||
|
|
||||||
internal void Update(string mid, string processJobID)
|
internal void Update(string mid, string processJobID)
|
||||||
{
|
{
|
||||||
_MID = mid;
|
_MID = mid;
|
||||||
|
@ -1,21 +1 @@
|
|||||||
namespace Adaptation.Shared;
|
|
||||||
|
|
||||||
public class ProcessData
|
|
||||||
{
|
|
||||||
|
|
||||||
protected readonly string _Logistics;
|
|
||||||
protected readonly string[] _Columns;
|
|
||||||
protected readonly string[] _BodyLines;
|
|
||||||
|
|
||||||
public string Logistics => _Logistics;
|
|
||||||
public string[] Columns => _Columns;
|
|
||||||
public string[] BodyLines => _BodyLines;
|
|
||||||
|
|
||||||
public ProcessData(string logistics, string[] columns, string[] bodyLines)
|
|
||||||
{
|
|
||||||
_Logistics = logistics;
|
|
||||||
_Columns = columns;
|
|
||||||
_BodyLines = bodyLines;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,18 +1,22 @@
|
|||||||
using Adaptation.Shared.Methods;
|
using Adaptation.Shared.Methods;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Adaptation.Shared;
|
namespace Adaptation.Shared;
|
||||||
|
|
||||||
public class ProcessDataStandardFormat
|
#nullable enable
|
||||||
|
|
||||||
|
internal class ProcessDataStandardFormat
|
||||||
{
|
{
|
||||||
|
|
||||||
public enum SearchFor
|
internal enum SearchFor
|
||||||
{
|
{
|
||||||
EquipmentIntegration = 1,
|
EquipmentIntegration = 1,
|
||||||
BusinessIntegration = 2,
|
BusinessIntegration = 2,
|
||||||
@ -20,320 +24,38 @@ public class ProcessDataStandardFormat
|
|||||||
Archive = 4
|
Archive = 4
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetPDSFText(IFileRead fileRead, Logistics logistics, JsonElement[] jsonElements, string logisticsText)
|
internal long? Sequence { get; private set; }
|
||||||
|
internal ReadOnlyCollection<string> Body { get; private set; }
|
||||||
|
internal ReadOnlyCollection<string> Columns { get; private set; }
|
||||||
|
internal ReadOnlyCollection<string> Logistics { get; private set; }
|
||||||
|
|
||||||
|
internal ProcessDataStandardFormat(ReadOnlyCollection<string> body,
|
||||||
|
ReadOnlyCollection<string> columns,
|
||||||
|
ReadOnlyCollection<string> logistics,
|
||||||
|
long? sequence)
|
||||||
{
|
{
|
||||||
string result;
|
Body = body;
|
||||||
if (jsonElements.Length == 0)
|
Columns = columns;
|
||||||
result = string.Empty;
|
Logistics = logistics;
|
||||||
else
|
Sequence = sequence;
|
||||||
{
|
|
||||||
int columns = 0;
|
|
||||||
List<string> lines;
|
|
||||||
string endOffset = "E#######T";
|
|
||||||
string dataOffset = "D#######T";
|
|
||||||
string headerOffset = "H#######T";
|
|
||||||
string format = "MM/dd/yyyy HH:mm:ss";
|
|
||||||
StringBuilder stringBuilder = new();
|
|
||||||
lines = new string[] { "HEADER_TAG\tHEADER_VALUE", "FORMAT\t2.00", "NUMBER_PASSES\t0001", string.Concat("HEADER_OFFSET\t", headerOffset), string.Concat("DATA_OFFSET\t", dataOffset), string.Concat("END_OFFSET\t", endOffset) }.ToList();
|
|
||||||
_ = stringBuilder.Append("\"Time\"").Append('\t');
|
|
||||||
_ = stringBuilder.Append("\"A_LOGISTICS\"").Append('\t');
|
|
||||||
_ = stringBuilder.Append("\"B_LOGISTICS\"").Append('\t');
|
|
||||||
for (int i = 0; i < jsonElements.Length;)
|
|
||||||
{
|
|
||||||
foreach (JsonProperty jsonProperty in jsonElements[0].EnumerateObject())
|
|
||||||
{
|
|
||||||
columns += 1;
|
|
||||||
_ = stringBuilder.Append('"').Append(jsonProperty.Name).Append('"').Append('\t');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
_ = stringBuilder.Remove(stringBuilder.Length - 1, 1);
|
|
||||||
lines.Add(stringBuilder.ToString());
|
|
||||||
for (int i = 0; i < jsonElements.Length; i++)
|
|
||||||
{
|
|
||||||
_ = stringBuilder.Clear();
|
|
||||||
_ = stringBuilder.Append("0.1").Append('\t');
|
|
||||||
_ = stringBuilder.Append('1').Append('\t');
|
|
||||||
_ = stringBuilder.Append('2').Append('\t');
|
|
||||||
foreach (JsonProperty jsonProperty in jsonElements[i].EnumerateObject())
|
|
||||||
_ = stringBuilder.Append(jsonProperty.Value).Append('\t');
|
|
||||||
_ = stringBuilder.Remove(stringBuilder.Length - 1, 1);
|
|
||||||
lines.Add(stringBuilder.ToString());
|
|
||||||
}
|
|
||||||
lines.Add(string.Concat("NUM_DATA_ROWS ", jsonElements.Length.ToString().PadLeft(9, '0')));
|
|
||||||
lines.Add(string.Concat("NUM_DATA_COLUMNS ", (columns + 3).ToString().PadLeft(9, '0')));
|
|
||||||
lines.Add("DELIMITER ;");
|
|
||||||
lines.Add(string.Concat("START_TIME_FORMAT ", format));
|
|
||||||
lines.Add(string.Concat("START_TIME ", logistics.DateTimeFromSequence.ToString(format))); //12/26/2019 15:22:44
|
|
||||||
lines.Add(string.Concat("LOGISTICS_COLUMN", '\t', "A_LOGISTICS"));
|
|
||||||
lines.Add(string.Concat("LOGISTICS_COLUMN", '\t', "B_LOGISTICS"));
|
|
||||||
if (!string.IsNullOrEmpty(logisticsText))
|
|
||||||
lines.Add(logisticsText);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lines.Add(string.Concat("LOGISTICS_1", '\t', "A_CHAMBER=;A_INFO=", fileRead.EventName, ";A_INFO2=", fileRead.EquipmentType, ";A_JOBID=", fileRead.CellInstanceName, ";A_MES_ENTITY=", fileRead.MesEntity, ";A_MID=", logistics.MID, ";A_NULL_DATA=", fileRead.NullData, ";A_PPID=NO_PPID;A_PROCESS_JOBID=", logistics.ProcessJobID, ";A_PRODUCT=;A_SEQUENCE=", logistics.Sequence, ";A_WAFER_ID=;"));
|
|
||||||
lines.Add(string.Concat("LOGISTICS_2", '\t', "B_CHAMBER=;B_INFO=", fileRead.EventName, ";B_INFO2=", fileRead.EquipmentType, ";B_JOBID=", fileRead.CellInstanceName, ";B_MES_ENTITY=", fileRead.MesEntity, ";B_MID=", logistics.MID, ";B_NULL_DATA=", fileRead.NullData, ";B_PPID=NO_PPID;B_PROCESS_JOBID=", logistics.ProcessJobID, ";B_PRODUCT=;B_SEQUENCE=", logistics.Sequence, ";B_WAFER_ID=;"));
|
|
||||||
lines.Add("END_HEADER");
|
|
||||||
}
|
|
||||||
_ = stringBuilder.Clear();
|
|
||||||
foreach (string line in lines)
|
|
||||||
_ = stringBuilder.AppendLine(line);
|
|
||||||
result = stringBuilder.ToString();
|
|
||||||
result = result.Replace(headerOffset, result.IndexOf("NUM_DATA_ROWS").ToString().PadLeft(9, '0')).
|
|
||||||
Replace(dataOffset, result.IndexOf('"').ToString().PadLeft(9, '0')).
|
|
||||||
Replace(endOffset, result.Length.ToString().PadLeft(9, '0'));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ProcessData GetProcessData(string reportFullPath, string[] lines = null)
|
internal static string EquipmentIntegration(bool addSpaces = true, char separator = ' ') =>
|
||||||
{
|
GetString(SearchFor.EquipmentIntegration, addSpaces, separator);
|
||||||
string segment;
|
|
||||||
List<string> body = new();
|
|
||||||
StringBuilder logistics = new();
|
|
||||||
lines ??= File.ReadAllLines(reportFullPath);
|
|
||||||
string[] segments;
|
|
||||||
if (lines.Length < 7)
|
|
||||||
segments = Array.Empty<string>();
|
|
||||||
else
|
|
||||||
segments = lines[6].Trim().Split('\t');
|
|
||||||
List<string> columns = new();
|
|
||||||
for (int c = 0; c < segments.Length; c++)
|
|
||||||
{
|
|
||||||
segment = segments[c].Substring(1, segments[c].Length - 2);
|
|
||||||
if (!columns.Contains(segment))
|
|
||||||
columns.Add(segment);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (short i = 1; i < short.MaxValue; i++)
|
|
||||||
{
|
|
||||||
segment = string.Concat(segment, "_", i);
|
|
||||||
if (!columns.Contains(segment))
|
|
||||||
{
|
|
||||||
columns.Add(segment);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool lookForLogistics = false;
|
|
||||||
for (int r = 7; r < lines.Length; r++)
|
|
||||||
{
|
|
||||||
if (lines[r].StartsWith("NUM_DATA_ROWS"))
|
|
||||||
lookForLogistics = true;
|
|
||||||
if (!lookForLogistics)
|
|
||||||
{
|
|
||||||
body.Add(lines[r]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (lines[r].StartsWith("LOGISTICS_1"))
|
|
||||||
{
|
|
||||||
for (int i = r; i < lines.Length; i++)
|
|
||||||
{
|
|
||||||
if (lines[r].StartsWith("END_HEADER"))
|
|
||||||
break;
|
|
||||||
_ = logistics.AppendLine(lines[i]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new(logistics.ToString(), columns.ToArray(), body.ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsonElement[] GetArray(ProcessData processData, bool lookForNumbers = false)
|
internal static string BusinessIntegration(bool addSpaces = true, char separator = ' ') =>
|
||||||
{
|
GetString(SearchFor.BusinessIntegration, addSpaces, separator);
|
||||||
JsonElement[] results;
|
|
||||||
if (processData.BodyLines.Length == 0 || !processData.BodyLines[0].Contains('\t'))
|
|
||||||
results = JsonSerializer.Deserialize<JsonElement[]>("[]");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string value;
|
|
||||||
string[] segments;
|
|
||||||
List<string> lines = new();
|
|
||||||
StringBuilder stringBuilder = new();
|
|
||||||
foreach (string bodyLine in processData.BodyLines)
|
|
||||||
{
|
|
||||||
_ = stringBuilder.Clear();
|
|
||||||
_ = stringBuilder.Append('{');
|
|
||||||
segments = bodyLine.Trim().Split('\t');
|
|
||||||
if (!lookForNumbers)
|
|
||||||
{
|
|
||||||
for (int c = 1; c < segments.Length; c++)
|
|
||||||
{
|
|
||||||
value = segments[c].Replace("\"", "\\\"").Replace("\\", "\\\\");
|
|
||||||
_ = stringBuilder.Append('"').Append(processData.Columns[c]).Append("\":\"").Append(value).Append("\",");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int c = 1; c < segments.Length; c++)
|
|
||||||
{
|
|
||||||
value = segments[c].Replace("\"", "\\\"").Replace("\\", "\\\\");
|
|
||||||
if (string.IsNullOrEmpty(value))
|
|
||||||
_ = stringBuilder.Append('"').Append(processData.Columns[c]).Append("\":").Append(value).Append("null,");
|
|
||||||
else if (value.All(char.IsDigit))
|
|
||||||
_ = stringBuilder.Append('"').Append(processData.Columns[c]).Append("\":").Append(value).Append(',');
|
|
||||||
else
|
|
||||||
_ = stringBuilder.Append('"').Append(processData.Columns[c]).Append("\":\"").Append(value).Append("\",");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ = stringBuilder.Remove(stringBuilder.Length - 1, 1);
|
|
||||||
_ = stringBuilder.AppendLine("}");
|
|
||||||
lines.Add(stringBuilder.ToString());
|
|
||||||
}
|
|
||||||
string json = $"[{string.Join(",", lines)}]";
|
|
||||||
results = JsonSerializer.Deserialize<JsonElement[]>(json);
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Dictionary<string, List<string>> GetDictionary(ProcessData processData)
|
internal static string SystemExport(bool addSpaces = true, char separator = ' ') =>
|
||||||
{
|
GetString(SearchFor.SystemExport, addSpaces, separator);
|
||||||
Dictionary<string, List<string>> results = new();
|
|
||||||
string[] segments;
|
|
||||||
foreach (string column in processData.Columns)
|
|
||||||
results.Add(column, new List<string>());
|
|
||||||
foreach (string bodyLine in processData.BodyLines)
|
|
||||||
{
|
|
||||||
segments = bodyLine.Split('\t');
|
|
||||||
for (int c = 1; c < segments.Length; c++)
|
|
||||||
{
|
|
||||||
if (c >= processData.Columns.Length)
|
|
||||||
continue;
|
|
||||||
results[processData.Columns[c]].Add(segments[c]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Tuple<string, Dictionary<Test, Dictionary<string, List<string>>>> GetTestDictionary(ProcessData processData)
|
internal static string Archive(bool addSpaces = true, char separator = ' ') =>
|
||||||
{
|
GetString(SearchFor.Archive, addSpaces, separator);
|
||||||
Dictionary<Test, Dictionary<string, List<string>>> results = new();
|
|
||||||
List<string> collection;
|
|
||||||
string testColumn = nameof(Test);
|
|
||||||
Dictionary<string, List<string>> keyValuePairs = GetDictionary(processData);
|
|
||||||
if (!keyValuePairs.TryGetValue(testColumn, out collection))
|
|
||||||
throw new Exception();
|
|
||||||
int min;
|
|
||||||
int max;
|
|
||||||
Test testKey;
|
|
||||||
List<string> vs;
|
|
||||||
string columnKey;
|
|
||||||
Dictionary<Test, List<int>> tests = new();
|
|
||||||
for (int i = 0; i < collection.Count; i++)
|
|
||||||
{
|
|
||||||
if (Enum.TryParse(collection[i], out Test test))
|
|
||||||
{
|
|
||||||
if (!results.ContainsKey(test))
|
|
||||||
{
|
|
||||||
tests.Add(test, new List<int>());
|
|
||||||
results.Add(test, new Dictionary<string, List<string>>());
|
|
||||||
}
|
|
||||||
tests[test].Add(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach (KeyValuePair<Test, List<int>> testKeyValuePair in tests)
|
|
||||||
{
|
|
||||||
testKey = testKeyValuePair.Key;
|
|
||||||
min = testKeyValuePair.Value.Min();
|
|
||||||
max = testKeyValuePair.Value.Max() + 1;
|
|
||||||
foreach (KeyValuePair<string, List<string>> keyValuePair in keyValuePairs)
|
|
||||||
results[testKey].Add(keyValuePair.Key, new List<string>());
|
|
||||||
foreach (KeyValuePair<string, List<string>> keyValuePair in keyValuePairs)
|
|
||||||
{
|
|
||||||
vs = keyValuePair.Value;
|
|
||||||
columnKey = keyValuePair.Key;
|
|
||||||
for (int i = min; i < max; i++)
|
|
||||||
{
|
|
||||||
if (vs.Count > i)
|
|
||||||
results[testKey][columnKey].Add(vs[i]);
|
|
||||||
else
|
|
||||||
results[testKey][columnKey].Add(string.Empty);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new Tuple<string, Dictionary<Test, Dictionary<string, List<string>>>>(processData.Logistics, results);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetString(SearchFor searchFor, bool addSpaces, char separator = ' ')
|
internal static ProcessDataStandardFormat GetEmpty() =>
|
||||||
{
|
new(new(Array.Empty<string>()), new(Array.Empty<string>()), new(Array.Empty<string>()), null);
|
||||||
if (!addSpaces)
|
|
||||||
return string.Concat(((int)searchFor).ToString().PadLeft(2, '0'), searchFor);
|
|
||||||
else
|
|
||||||
return string.Concat(((int)searchFor).ToString().PadLeft(2, '0'), separator, searchFor.ToString().Replace("In", string.Concat(separator, "In")).Replace("Ex", string.Concat(separator, "Ex")));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string EquipmentIntegration(bool addSpaces = true, char separator = ' ') => GetString(SearchFor.EquipmentIntegration, addSpaces, separator);
|
internal static List<string> PDSFToFixedWidth(string reportFullPath)
|
||||||
|
|
||||||
public static string BusinessIntegration(bool addSpaces = true, char separator = ' ') => GetString(SearchFor.BusinessIntegration, addSpaces, separator);
|
|
||||||
|
|
||||||
public static string SystemExport(bool addSpaces = true, char separator = ' ') => GetString(SearchFor.SystemExport, addSpaces, separator);
|
|
||||||
|
|
||||||
public static string Archive(bool addSpaces = true, char separator = ' ') => GetString(SearchFor.Archive, addSpaces, separator);
|
|
||||||
|
|
||||||
public static string GetLines(Logistics logistics, Properties.IScopeInfo scopeInfo, List<string> names, Dictionary<string, List<string>> keyValuePairs, string dateFormat, string timeFormat, List<string> pairedParameterNames, bool useDateTimeFromSequence = true, string format = "", List<string> ignoreParameterNames = null)
|
|
||||||
{
|
|
||||||
StringBuilder result = new();
|
|
||||||
ignoreParameterNames ??= new List<string>();
|
|
||||||
if (useDateTimeFromSequence && !string.IsNullOrEmpty(format))
|
|
||||||
throw new Exception();
|
|
||||||
else if (!useDateTimeFromSequence && string.IsNullOrEmpty(format))
|
|
||||||
throw new Exception();
|
|
||||||
string nullData;
|
|
||||||
const string columnDate = "Date";
|
|
||||||
const string columnTime = "Time";
|
|
||||||
const string firstDuplicate = "_1";
|
|
||||||
_ = result.AppendLine(scopeInfo.Header);
|
|
||||||
StringBuilder line = new();
|
|
||||||
if (logistics.NullData is null)
|
|
||||||
nullData = string.Empty;
|
|
||||||
else
|
|
||||||
nullData = logistics.NullData.ToString();
|
|
||||||
int count = (from l in keyValuePairs select l.Value.Count).Min();
|
|
||||||
for (int r = 0; r < count; r++)
|
|
||||||
{
|
|
||||||
_ = line.Clear();
|
|
||||||
_ = line.Append('!');
|
|
||||||
foreach (KeyValuePair<string, List<string>> keyValuePair in keyValuePairs)
|
|
||||||
{
|
|
||||||
if (!names.Contains(keyValuePair.Key))
|
|
||||||
continue;
|
|
||||||
if (ignoreParameterNames.Contains(keyValuePair.Key))
|
|
||||||
continue;
|
|
||||||
if (pairedParameterNames.Contains(keyValuePair.Key))
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(keyValuePair.Value[r]) || keyValuePair.Value[r] == nullData)
|
|
||||||
continue;
|
|
||||||
else
|
|
||||||
_ = result.Append(line).Append(keyValuePair.Key).Append(';').AppendLine(keyValuePair.Value[r]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (useDateTimeFromSequence && keyValuePair.Key == columnDate)
|
|
||||||
_ = line.Append(logistics.DateTimeFromSequence.ToString(dateFormat));
|
|
||||||
else if (useDateTimeFromSequence && keyValuePair.Key == columnTime)
|
|
||||||
_ = line.Append(logistics.DateTimeFromSequence.ToString(timeFormat));
|
|
||||||
else if (!useDateTimeFromSequence && keyValuePair.Key == columnDate && keyValuePair.Value[r].Length == format.Length)
|
|
||||||
_ = line.Append(DateTime.ParseExact(keyValuePair.Value[r], format, CultureInfo.InvariantCulture).ToString(dateFormat));
|
|
||||||
else if (!useDateTimeFromSequence && keyValuePair.Key == columnTime && keyValuePairs.TryGetValue(string.Concat(keyValuePair.Key, firstDuplicate), out List<string> value) && value[r].Length == format.Length)
|
|
||||||
_ = line.Append(DateTime.ParseExact(keyValuePairs[string.Concat(keyValuePair.Key, firstDuplicate)][r], format, CultureInfo.InvariantCulture).ToString(timeFormat));
|
|
||||||
else if (string.IsNullOrEmpty(keyValuePair.Value[r]) || keyValuePair.Value[r] == nullData)
|
|
||||||
_ = line.Append(nullData);
|
|
||||||
else
|
|
||||||
_ = line.Append(keyValuePair.Value[r]);
|
|
||||||
_ = line.Append(';');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pairedParameterNames.Count == 0)
|
|
||||||
{
|
|
||||||
_ = line.Remove(line.Length - 1, 1);
|
|
||||||
_ = result.AppendLine(line.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<string> PDSFToFixedWidth(string reportFullPath)
|
|
||||||
{
|
{
|
||||||
List<string> results = new();
|
List<string> results = new();
|
||||||
if (!File.Exists(reportFullPath))
|
if (!File.Exists(reportFullPath))
|
||||||
@ -402,4 +124,534 @@ public class ProcessDataStandardFormat
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static ProcessDataStandardFormat GetProcessDataStandardFormat(string reportFullPath, string[]? lines = null)
|
||||||
|
{
|
||||||
|
ProcessDataStandardFormat result;
|
||||||
|
string segment;
|
||||||
|
List<string> body = new();
|
||||||
|
List<string> logistics = new();
|
||||||
|
lines ??= File.ReadAllLines(reportFullPath);
|
||||||
|
string[] segments;
|
||||||
|
if (lines.Length < 7)
|
||||||
|
segments = Array.Empty<string>();
|
||||||
|
else
|
||||||
|
segments = lines[6].Trim().Split('\t');
|
||||||
|
List<string> columns = new();
|
||||||
|
for (int c = 0; c < segments.Length; c++)
|
||||||
|
{
|
||||||
|
segment = segments[c].Substring(1, segments[c].Length - 2);
|
||||||
|
if (!columns.Contains(segment))
|
||||||
|
columns.Add(segment);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (short i = 1; i < short.MaxValue; i++)
|
||||||
|
{
|
||||||
|
segment = string.Concat(segment, "_", i);
|
||||||
|
if (!columns.Contains(segment))
|
||||||
|
{
|
||||||
|
columns.Add(segment);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool lookForLogistics = false;
|
||||||
|
for (int r = 7; r < lines.Length; r++)
|
||||||
|
{
|
||||||
|
if (lines[r].StartsWith("NUM_DATA_ROWS"))
|
||||||
|
lookForLogistics = true;
|
||||||
|
if (!lookForLogistics)
|
||||||
|
{
|
||||||
|
body.Add(lines[r]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (lines[r].StartsWith("LOGISTICS_1"))
|
||||||
|
{
|
||||||
|
for (int i = r; i < lines.Length; i++)
|
||||||
|
{
|
||||||
|
if (lines[r].StartsWith("END_HEADER"))
|
||||||
|
break;
|
||||||
|
logistics.Add(lines[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = new(logistics.AsReadOnly(), columns.AsReadOnly(), body.AsReadOnly(), null);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static ProcessDataStandardFormat? GetProcessDataStandardFormat(string reportFullPath, ProcessDataStandardFormatMapping pdsfMapping)
|
||||||
|
{
|
||||||
|
ProcessDataStandardFormat? result;
|
||||||
|
const int columnsLine = 6;
|
||||||
|
FileInfo fileInfo = new(reportFullPath);
|
||||||
|
ProcessDataStandardFormat processDataStandardFormat = GetProcessDataStandardFormat(fileInfo.LastWriteTime, pdsfMapping.NewColumnNames.Count, columnsLine, fileInfo.FullName, lines: null);
|
||||||
|
JsonElement[]? jsonElements = GetArray(pdsfMapping.NewColumnNames.Count, processDataStandardFormat, lookForNumbers: false);
|
||||||
|
if (jsonElements is null || pdsfMapping.OldColumnNames.Count != pdsfMapping.ColumnIndices.Count)
|
||||||
|
result = null;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = GetProcessDataStandardFormat(pdsfMapping, jsonElements, processDataStandardFormat);
|
||||||
|
if (result.Sequence is null || result.Columns.Count == 0 || result.Body.Count == 0 || result.Logistics.Count == 0)
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ProcessDataStandardFormat GetProcessDataStandardFormat(DateTime lastWriteTime, int expectedColumns, int columnsLine, string path, string[]? lines)
|
||||||
|
{
|
||||||
|
ProcessDataStandardFormat result;
|
||||||
|
long sequence;
|
||||||
|
string[] segments;
|
||||||
|
List<string> body = new();
|
||||||
|
bool lookForLogistics = false;
|
||||||
|
List<string> logistics = new();
|
||||||
|
lines ??= File.ReadAllLines(path);
|
||||||
|
if (lines.Length <= columnsLine)
|
||||||
|
segments = Array.Empty<string>();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
segments = lines[columnsLine].Split('\t');
|
||||||
|
if (segments.Length != expectedColumns)
|
||||||
|
segments = Array.Empty<string>();
|
||||||
|
}
|
||||||
|
string[] columns = segments.Select(l => l.Trim('"')).ToArray();
|
||||||
|
for (int r = columnsLine + 1; r < lines.Length; r++)
|
||||||
|
{
|
||||||
|
if (lines[r].StartsWith("NUM_DATA_ROWS"))
|
||||||
|
lookForLogistics = true;
|
||||||
|
if (!lookForLogistics)
|
||||||
|
{
|
||||||
|
body.Add(lines[r]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (lines[r].StartsWith("LOGISTICS_1"))
|
||||||
|
{
|
||||||
|
for (int i = r; i < lines.Length; i++)
|
||||||
|
{
|
||||||
|
if (lines[r].StartsWith("END_HEADER"))
|
||||||
|
break;
|
||||||
|
logistics.Add(lines[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (logistics.Count == 0)
|
||||||
|
sequence = lastWriteTime.Ticks;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
segments = logistics[0].Split(new string[] { "SEQUENCE=" }, StringSplitOptions.None);
|
||||||
|
sequence = segments.Length < 2 || !long.TryParse(segments[1].Split(';')[0], out long s) ? lastWriteTime.Ticks : s;
|
||||||
|
}
|
||||||
|
result = new(body: body.AsReadOnly(),
|
||||||
|
columns: new(columns),
|
||||||
|
logistics: logistics.AsReadOnly(),
|
||||||
|
sequence: sequence);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JsonElement[]? GetArray(int expectedColumns, ProcessDataStandardFormat processDataStandardFormat, bool lookForNumbers)
|
||||||
|
{
|
||||||
|
JsonElement[]? results;
|
||||||
|
if (processDataStandardFormat.Body.Count == 0 || !processDataStandardFormat.Body[0].Contains('\t'))
|
||||||
|
results = JsonSerializer.Deserialize("[]", JsonElementCollectionSourceGenerationContext.Default.JsonElementArray) ?? throw new Exception();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string value;
|
||||||
|
string[] segments;
|
||||||
|
List<string> lines = new();
|
||||||
|
StringBuilder stringBuilder = new();
|
||||||
|
foreach (string bodyLine in processDataStandardFormat.Body)
|
||||||
|
{
|
||||||
|
_ = stringBuilder.Clear();
|
||||||
|
_ = stringBuilder.Append('{');
|
||||||
|
segments = bodyLine.Split('\t');
|
||||||
|
if (segments.Length != expectedColumns)
|
||||||
|
continue;
|
||||||
|
if (!lookForNumbers)
|
||||||
|
{
|
||||||
|
for (int c = 0; c < segments.Length; c++)
|
||||||
|
{
|
||||||
|
value = segments[c].Replace("\"", "\\\"").Replace("\\", "\\\\");
|
||||||
|
_ = stringBuilder.Append('"').Append(processDataStandardFormat.Columns[c]).Append("\":\"").Append(value).Append("\",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int c = 0; c < segments.Length; c++)
|
||||||
|
{
|
||||||
|
value = segments[c].Replace("\"", "\\\"").Replace("\\", "\\\\");
|
||||||
|
if (string.IsNullOrEmpty(value))
|
||||||
|
_ = stringBuilder.Append('"').Append(processDataStandardFormat.Columns[c]).Append("\":").Append(value).Append("null,");
|
||||||
|
else if (value.All(char.IsDigit))
|
||||||
|
_ = stringBuilder.Append('"').Append(processDataStandardFormat.Columns[c]).Append("\":").Append(value).Append(',');
|
||||||
|
else
|
||||||
|
_ = stringBuilder.Append('"').Append(processDataStandardFormat.Columns[c]).Append("\":\"").Append(value).Append("\",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ = stringBuilder.Remove(stringBuilder.Length - 1, 1);
|
||||||
|
_ = stringBuilder.AppendLine("}");
|
||||||
|
lines.Add(stringBuilder.ToString());
|
||||||
|
}
|
||||||
|
string json = $"[{string.Join(",", lines)}]";
|
||||||
|
results = JsonSerializer.Deserialize(json, JsonElementCollectionSourceGenerationContext.Default.JsonElementArray);
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ProcessDataStandardFormat GetProcessDataStandardFormat(ProcessDataStandardFormatMapping processDataStandardFormatMapping, JsonElement[] jsonElements, ProcessDataStandardFormat processDataStandardFormat)
|
||||||
|
{
|
||||||
|
ProcessDataStandardFormat result;
|
||||||
|
int column;
|
||||||
|
string value;
|
||||||
|
JsonProperty jsonProperty;
|
||||||
|
List<string> values = new();
|
||||||
|
List<string> results = new();
|
||||||
|
JsonProperty[] jsonProperties;
|
||||||
|
List<string> unknownColumns = new();
|
||||||
|
for (int i = 0; i < jsonElements.Length; i++)
|
||||||
|
{
|
||||||
|
values.Clear();
|
||||||
|
if (jsonElements[i].ValueKind != JsonValueKind.Object)
|
||||||
|
{
|
||||||
|
unknownColumns.Add(string.Empty);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
jsonProperties = jsonElements[i].EnumerateObject().ToArray();
|
||||||
|
if (jsonProperties.Length != processDataStandardFormatMapping.NewColumnNames.Count)
|
||||||
|
continue;
|
||||||
|
for (int c = 0; c < processDataStandardFormatMapping.ColumnIndices.Count; c++)
|
||||||
|
{
|
||||||
|
column = processDataStandardFormatMapping.ColumnIndices[c];
|
||||||
|
if (column == -1)
|
||||||
|
value = processDataStandardFormatMapping.OldColumnNames[c];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
jsonProperty = jsonProperties[column];
|
||||||
|
value = jsonProperty.Value.ToString();
|
||||||
|
}
|
||||||
|
values.Add(value);
|
||||||
|
}
|
||||||
|
results.Add(string.Join("\t", values));
|
||||||
|
}
|
||||||
|
result = new(body: new(results),
|
||||||
|
columns: processDataStandardFormat.Columns,
|
||||||
|
logistics: processDataStandardFormat.Logistics,
|
||||||
|
sequence: processDataStandardFormat.Sequence);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void Write(string path, ProcessDataStandardFormat processDataStandardFormat)
|
||||||
|
{
|
||||||
|
List<string> results = new();
|
||||||
|
if (processDataStandardFormat.Sequence is null)
|
||||||
|
throw new NullReferenceException(nameof(processDataStandardFormat.Sequence));
|
||||||
|
string endOffset = "E#######T";
|
||||||
|
string dataOffset = "D#######T";
|
||||||
|
string headerOffset = "H#######T";
|
||||||
|
string format = "MM/dd/yyyy HH:mm:ss";
|
||||||
|
string startTime = new DateTime(processDataStandardFormat.Sequence.Value).ToString(format);
|
||||||
|
results.Add("HEADER_TAG\tHEADER_VALUE");
|
||||||
|
results.Add("FORMAT\t2.00");
|
||||||
|
results.Add("NUMBER_PASSES\t0001");
|
||||||
|
results.Add($"HEADER_OFFSET\t{headerOffset}");
|
||||||
|
results.Add($"DATA_OFFSET\t{dataOffset}");
|
||||||
|
results.Add($"END_OFFSET\t{endOffset}");
|
||||||
|
results.Add($"\"{string.Join("\",\t\"", processDataStandardFormat.Columns)}\"");
|
||||||
|
results.AddRange(processDataStandardFormat.Body);
|
||||||
|
results.Add($"NUM_DATA_ROWS\t{processDataStandardFormat.Body.Count.ToString().PadLeft(9, '0')}");
|
||||||
|
results.Add($"NUM_DATA_COLUMNS\t{processDataStandardFormat.Columns.Count.ToString().PadLeft(9, '0')}");
|
||||||
|
results.Add("DELIMITER\t;");
|
||||||
|
results.Add($"START_TIME_FORMAT\t{format}");
|
||||||
|
results.Add($"START_TIME\t{startTime}");
|
||||||
|
results.Add("LOGISTICS_COLUMN\tA_LOGISTICS");
|
||||||
|
results.Add("LOGISTICS_COLUMN\tB_LOGISTICS");
|
||||||
|
results.AddRange(processDataStandardFormat.Logistics);
|
||||||
|
File.WriteAllText(path, string.Join(Environment.NewLine, results));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Dictionary<string, List<string>> GetDictionary(ProcessDataStandardFormat processDataStandardFormat)
|
||||||
|
{
|
||||||
|
Dictionary<string, List<string>> results = new();
|
||||||
|
string[] segments;
|
||||||
|
foreach (string column in processDataStandardFormat.Columns)
|
||||||
|
results.Add(column, new List<string>());
|
||||||
|
foreach (string bodyLine in processDataStandardFormat.Body)
|
||||||
|
{
|
||||||
|
segments = bodyLine.Split('\t');
|
||||||
|
for (int c = 1; c < segments.Length; c++)
|
||||||
|
{
|
||||||
|
if (c >= processDataStandardFormat.Columns.Count)
|
||||||
|
continue;
|
||||||
|
results[processDataStandardFormat.Columns[c]].Add(segments[c]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static JsonElement[] GetArray(ProcessDataStandardFormat processDataStandardFormat, bool lookForNumbers = false)
|
||||||
|
{
|
||||||
|
JsonElement[] results;
|
||||||
|
if (processDataStandardFormat.Body.Count == 0 || !processDataStandardFormat.Body[0].Contains('\t'))
|
||||||
|
results = JsonSerializer.Deserialize("[]", JsonElementCollectionSourceGenerationContext.Default.JsonElementArray) ?? throw new Exception();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string value;
|
||||||
|
string[] segments;
|
||||||
|
List<string> lines = new();
|
||||||
|
StringBuilder stringBuilder = new();
|
||||||
|
foreach (string bodyLine in processDataStandardFormat.Body)
|
||||||
|
{
|
||||||
|
_ = stringBuilder.Clear();
|
||||||
|
_ = stringBuilder.Append('{');
|
||||||
|
segments = bodyLine.Trim().Split('\t');
|
||||||
|
if (!lookForNumbers)
|
||||||
|
{
|
||||||
|
for (int c = 1; c < segments.Length; c++)
|
||||||
|
{
|
||||||
|
value = segments[c].Replace("\"", "\\\"").Replace("\\", "\\\\");
|
||||||
|
_ = stringBuilder.Append('"').Append(processDataStandardFormat.Columns[c]).Append("\":\"").Append(value).Append("\",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int c = 1; c < segments.Length; c++)
|
||||||
|
{
|
||||||
|
value = segments[c].Replace("\"", "\\\"").Replace("\\", "\\\\");
|
||||||
|
if (string.IsNullOrEmpty(value))
|
||||||
|
_ = stringBuilder.Append('"').Append(processDataStandardFormat.Columns[c]).Append("\":").Append(value).Append("null,");
|
||||||
|
else if (value.All(char.IsDigit))
|
||||||
|
_ = stringBuilder.Append('"').Append(processDataStandardFormat.Columns[c]).Append("\":").Append(value).Append(',');
|
||||||
|
else
|
||||||
|
_ = stringBuilder.Append('"').Append(processDataStandardFormat.Columns[c]).Append("\":\"").Append(value).Append("\",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ = stringBuilder.Remove(stringBuilder.Length - 1, 1);
|
||||||
|
_ = stringBuilder.AppendLine("}");
|
||||||
|
lines.Add(stringBuilder.ToString());
|
||||||
|
}
|
||||||
|
string json = $"[{string.Join(",", lines)}]";
|
||||||
|
results = JsonSerializer.Deserialize<JsonElement[]>(json) ?? throw new Exception();
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string GetPDSFText(IFileRead fileRead, Logistics logistics, JsonElement[] jsonElements, string logisticsText)
|
||||||
|
{
|
||||||
|
string result;
|
||||||
|
if (jsonElements.Length == 0)
|
||||||
|
result = string.Empty;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int columns = 0;
|
||||||
|
List<string> lines;
|
||||||
|
string endOffset = "E#######T";
|
||||||
|
string dataOffset = "D#######T";
|
||||||
|
string headerOffset = "H#######T";
|
||||||
|
string format = "MM/dd/yyyy HH:mm:ss";
|
||||||
|
StringBuilder stringBuilder = new();
|
||||||
|
lines = new string[] { "HEADER_TAG\tHEADER_VALUE", "FORMAT\t2.00", "NUMBER_PASSES\t0001", string.Concat("HEADER_OFFSET\t", headerOffset), string.Concat("DATA_OFFSET\t", dataOffset), string.Concat("END_OFFSET\t", endOffset) }.ToList();
|
||||||
|
_ = stringBuilder.Append("\"Time\"").Append('\t');
|
||||||
|
_ = stringBuilder.Append("\"A_LOGISTICS\"").Append('\t');
|
||||||
|
_ = stringBuilder.Append("\"B_LOGISTICS\"").Append('\t');
|
||||||
|
for (int i = 0; i < jsonElements.Length;)
|
||||||
|
{
|
||||||
|
foreach (JsonProperty jsonProperty in jsonElements[0].EnumerateObject())
|
||||||
|
{
|
||||||
|
columns += 1;
|
||||||
|
_ = stringBuilder.Append('"').Append(jsonProperty.Name).Append('"').Append('\t');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_ = stringBuilder.Remove(stringBuilder.Length - 1, 1);
|
||||||
|
lines.Add(stringBuilder.ToString());
|
||||||
|
for (int i = 0; i < jsonElements.Length; i++)
|
||||||
|
{
|
||||||
|
_ = stringBuilder.Clear();
|
||||||
|
_ = stringBuilder.Append("0.1").Append('\t');
|
||||||
|
_ = stringBuilder.Append('1').Append('\t');
|
||||||
|
_ = stringBuilder.Append('2').Append('\t');
|
||||||
|
foreach (JsonProperty jsonProperty in jsonElements[i].EnumerateObject())
|
||||||
|
_ = stringBuilder.Append(jsonProperty.Value).Append('\t');
|
||||||
|
_ = stringBuilder.Remove(stringBuilder.Length - 1, 1);
|
||||||
|
lines.Add(stringBuilder.ToString());
|
||||||
|
}
|
||||||
|
lines.Add(string.Concat("NUM_DATA_ROWS ", jsonElements.Length.ToString().PadLeft(9, '0')));
|
||||||
|
lines.Add(string.Concat("NUM_DATA_COLUMNS ", (columns + 3).ToString().PadLeft(9, '0')));
|
||||||
|
lines.Add("DELIMITER ;");
|
||||||
|
lines.Add(string.Concat("START_TIME_FORMAT ", format));
|
||||||
|
lines.Add(string.Concat("START_TIME ", logistics.DateTimeFromSequence.ToString(format))); //12/26/2019 15:22:44
|
||||||
|
lines.Add(string.Concat("LOGISTICS_COLUMN", '\t', "A_LOGISTICS"));
|
||||||
|
lines.Add(string.Concat("LOGISTICS_COLUMN", '\t', "B_LOGISTICS"));
|
||||||
|
if (!string.IsNullOrEmpty(logisticsText))
|
||||||
|
lines.Add(logisticsText);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lines.Add(string.Concat("LOGISTICS_1", '\t', "A_CHAMBER=;A_INFO=", fileRead.EventName, ";A_INFO2=", fileRead.EquipmentType, ";A_JOBID=", fileRead.CellInstanceName, ";A_MES_ENTITY=", fileRead.MesEntity, ";A_MID=", logistics.MID, ";A_NULL_DATA=", fileRead.NullData, ";A_PPID=NO_PPID;A_PROCESS_JOBID=", logistics.ProcessJobID, ";A_PRODUCT=;A_SEQUENCE=", logistics.Sequence, ";A_WAFER_ID=;"));
|
||||||
|
lines.Add(string.Concat("LOGISTICS_2", '\t', "B_CHAMBER=;B_INFO=", fileRead.EventName, ";B_INFO2=", fileRead.EquipmentType, ";B_JOBID=", fileRead.CellInstanceName, ";B_MES_ENTITY=", fileRead.MesEntity, ";B_MID=", logistics.MID, ";B_NULL_DATA=", fileRead.NullData, ";B_PPID=NO_PPID;B_PROCESS_JOBID=", logistics.ProcessJobID, ";B_PRODUCT=;B_SEQUENCE=", logistics.Sequence, ";B_WAFER_ID=;"));
|
||||||
|
lines.Add("END_HEADER");
|
||||||
|
}
|
||||||
|
_ = stringBuilder.Clear();
|
||||||
|
foreach (string line in lines)
|
||||||
|
_ = stringBuilder.AppendLine(line);
|
||||||
|
result = stringBuilder.ToString();
|
||||||
|
result = result.Replace(headerOffset, result.IndexOf("NUM_DATA_ROWS").ToString().PadLeft(9, '0')).
|
||||||
|
Replace(dataOffset, result.IndexOf('"').ToString().PadLeft(9, '0')).
|
||||||
|
Replace(endOffset, result.Length.ToString().PadLeft(9, '0'));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Tuple<string, Dictionary<Test, Dictionary<string, List<string>>>> GetTestDictionary(ProcessDataStandardFormat processDataStandardFormat)
|
||||||
|
{
|
||||||
|
Dictionary<Test, Dictionary<string, List<string>>> results = new();
|
||||||
|
List<string>? collection;
|
||||||
|
string testColumn = nameof(Test);
|
||||||
|
Dictionary<string, List<string>> keyValuePairs = GetDictionary(processDataStandardFormat);
|
||||||
|
if (!keyValuePairs.TryGetValue(testColumn, out collection))
|
||||||
|
throw new Exception();
|
||||||
|
int min;
|
||||||
|
int max;
|
||||||
|
Test testKey;
|
||||||
|
List<string> vs;
|
||||||
|
string columnKey;
|
||||||
|
Dictionary<Test, List<int>> tests = new();
|
||||||
|
for (int i = 0; i < collection.Count; i++)
|
||||||
|
{
|
||||||
|
if (Enum.TryParse(collection[i], out Test test))
|
||||||
|
{
|
||||||
|
if (!results.ContainsKey(test))
|
||||||
|
{
|
||||||
|
tests.Add(test, new List<int>());
|
||||||
|
results.Add(test, new Dictionary<string, List<string>>());
|
||||||
|
}
|
||||||
|
tests[test].Add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (KeyValuePair<Test, List<int>> testKeyValuePair in tests)
|
||||||
|
{
|
||||||
|
testKey = testKeyValuePair.Key;
|
||||||
|
min = testKeyValuePair.Value.Min();
|
||||||
|
max = testKeyValuePair.Value.Max() + 1;
|
||||||
|
foreach (KeyValuePair<string, List<string>> keyValuePair in keyValuePairs)
|
||||||
|
results[testKey].Add(keyValuePair.Key, new List<string>());
|
||||||
|
foreach (KeyValuePair<string, List<string>> keyValuePair in keyValuePairs)
|
||||||
|
{
|
||||||
|
vs = keyValuePair.Value;
|
||||||
|
columnKey = keyValuePair.Key;
|
||||||
|
for (int i = min; i < max; i++)
|
||||||
|
{
|
||||||
|
if (vs.Count > i)
|
||||||
|
results[testKey][columnKey].Add(vs[i]);
|
||||||
|
else
|
||||||
|
results[testKey][columnKey].Add(string.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Tuple<string, Dictionary<Test, Dictionary<string, List<string>>>>(processDataStandardFormat.Logistics[0], results);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string GetLines(Logistics logistics, Properties.IScopeInfo scopeInfo, List<string> names, Dictionary<string, List<string>> keyValuePairs, string dateFormat, string timeFormat, List<string> pairedParameterNames, bool useDateTimeFromSequence = true, string format = "", List<string>? ignoreParameterNames = null)
|
||||||
|
{
|
||||||
|
StringBuilder result = new();
|
||||||
|
ignoreParameterNames ??= new List<string>();
|
||||||
|
if (useDateTimeFromSequence && !string.IsNullOrEmpty(format))
|
||||||
|
throw new Exception();
|
||||||
|
else if (!useDateTimeFromSequence && string.IsNullOrEmpty(format))
|
||||||
|
throw new Exception();
|
||||||
|
string? nullData;
|
||||||
|
const string columnDate = "Date";
|
||||||
|
const string columnTime = "Time";
|
||||||
|
const string firstDuplicate = "_1";
|
||||||
|
_ = result.AppendLine(scopeInfo.Header);
|
||||||
|
StringBuilder line = new();
|
||||||
|
if (logistics.NullData is null)
|
||||||
|
nullData = string.Empty;
|
||||||
|
else
|
||||||
|
nullData = logistics.NullData.ToString();
|
||||||
|
int count = (from l in keyValuePairs select l.Value.Count).Min();
|
||||||
|
for (int r = 0; r < count; r++)
|
||||||
|
{
|
||||||
|
_ = line.Clear();
|
||||||
|
_ = line.Append('!');
|
||||||
|
foreach (KeyValuePair<string, List<string>> keyValuePair in keyValuePairs)
|
||||||
|
{
|
||||||
|
if (!names.Contains(keyValuePair.Key))
|
||||||
|
continue;
|
||||||
|
if (ignoreParameterNames.Contains(keyValuePair.Key))
|
||||||
|
continue;
|
||||||
|
if (pairedParameterNames.Contains(keyValuePair.Key))
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(keyValuePair.Value[r]) || keyValuePair.Value[r] == nullData)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
_ = result.Append(line).Append(keyValuePair.Key).Append(';').AppendLine(keyValuePair.Value[r]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (useDateTimeFromSequence && keyValuePair.Key == columnDate)
|
||||||
|
_ = line.Append(logistics.DateTimeFromSequence.ToString(dateFormat));
|
||||||
|
else if (useDateTimeFromSequence && keyValuePair.Key == columnTime)
|
||||||
|
_ = line.Append(logistics.DateTimeFromSequence.ToString(timeFormat));
|
||||||
|
else if (!useDateTimeFromSequence && keyValuePair.Key == columnDate && keyValuePair.Value[r].Length == format.Length)
|
||||||
|
_ = line.Append(DateTime.ParseExact(keyValuePair.Value[r], format, CultureInfo.InvariantCulture).ToString(dateFormat));
|
||||||
|
else if (!useDateTimeFromSequence && keyValuePair.Key == columnTime && keyValuePairs.ContainsKey(string.Concat(keyValuePair.Key, firstDuplicate)) && keyValuePairs[string.Concat(keyValuePair.Key, firstDuplicate)][r].Length == format.Length)
|
||||||
|
_ = line.Append(DateTime.ParseExact(keyValuePairs[string.Concat(keyValuePair.Key, firstDuplicate)][r], format, CultureInfo.InvariantCulture).ToString(timeFormat));
|
||||||
|
else if (string.IsNullOrEmpty(keyValuePair.Value[r]) || keyValuePair.Value[r] == nullData)
|
||||||
|
_ = line.Append(nullData);
|
||||||
|
else
|
||||||
|
_ = line.Append(keyValuePair.Value[r]);
|
||||||
|
_ = line.Append(';');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pairedParameterNames.Count == 0)
|
||||||
|
{
|
||||||
|
_ = line.Remove(line.Length - 1, 1);
|
||||||
|
_ = result.AppendLine(line.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetString(SearchFor searchFor, bool addSpaces, char separator = ' ')
|
||||||
|
{
|
||||||
|
if (!addSpaces)
|
||||||
|
return string.Concat(((int)searchFor).ToString().PadLeft(2, '0'), searchFor);
|
||||||
|
else
|
||||||
|
return string.Concat(((int)searchFor).ToString().PadLeft(2, '0'), separator, searchFor.ToString().Replace("In", string.Concat(separator, "In")).Replace("Ex", string.Concat(separator, "Ex")));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int? TryGetPropertyIndex(JsonProperty[] jsonProperties, string propertyName)
|
||||||
|
{
|
||||||
|
int? result = null;
|
||||||
|
for (int i = 0; i < jsonProperties.Length; i++)
|
||||||
|
{
|
||||||
|
if (jsonProperties[i].Name != propertyName)
|
||||||
|
continue;
|
||||||
|
result = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (result is null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < jsonProperties.Length; i++)
|
||||||
|
{
|
||||||
|
if (jsonProperties[i].Name[0] != propertyName[0])
|
||||||
|
continue;
|
||||||
|
if (jsonProperties[i].Name.Length != propertyName.Length)
|
||||||
|
continue;
|
||||||
|
if (jsonProperties[i].Name != propertyName)
|
||||||
|
continue;
|
||||||
|
result = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||||
|
[JsonSerializable(typeof(JsonElement[]))]
|
||||||
|
internal partial class JsonElementCollectionSourceGenerationContext : JsonSerializerContext
|
||||||
|
{
|
||||||
}
|
}
|
33
Adaptation/Shared/ProcessDataStandardFormatMapping.cs
Normal file
33
Adaptation/Shared/ProcessDataStandardFormatMapping.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
namespace Adaptation.Shared;
|
||||||
|
|
||||||
|
public class ProcessDataStandardFormatMapping
|
||||||
|
{
|
||||||
|
|
||||||
|
public ReadOnlyCollection<string> BackfillColumns { get; private set; }
|
||||||
|
public ReadOnlyCollection<int> ColumnIndices { get; private set; }
|
||||||
|
public ReadOnlyCollection<string> IgnoreColumns { get; private set; }
|
||||||
|
public ReadOnlyCollection<string> IndexOnlyColumns { get; private set; }
|
||||||
|
public ReadOnlyDictionary<string, string> KeyValuePairs { get; private set; }
|
||||||
|
public ReadOnlyCollection<string> NewColumnNames { get; private set; }
|
||||||
|
public ReadOnlyCollection<string> OldColumnNames { get; private set; }
|
||||||
|
|
||||||
|
public ProcessDataStandardFormatMapping(ReadOnlyCollection<string> backfillColumns,
|
||||||
|
ReadOnlyCollection<int> columnIndices,
|
||||||
|
ReadOnlyCollection<string> ignoreColumns,
|
||||||
|
ReadOnlyCollection<string> indexOnlyColumns,
|
||||||
|
ReadOnlyDictionary<string, string> keyValuePairs,
|
||||||
|
ReadOnlyCollection<string> newColumnNames,
|
||||||
|
ReadOnlyCollection<string> oldColumnNames)
|
||||||
|
{
|
||||||
|
BackfillColumns = backfillColumns;
|
||||||
|
ColumnIndices = columnIndices;
|
||||||
|
IgnoreColumns = ignoreColumns;
|
||||||
|
IndexOnlyColumns = indexOnlyColumns;
|
||||||
|
KeyValuePairs = keyValuePairs;
|
||||||
|
NewColumnNames = newColumnNames;
|
||||||
|
OldColumnNames = oldColumnNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -100,5 +100,18 @@ public class MESAFIBACKLOG : EAFLoggingUnitTesting
|
|||||||
EAFLoggingUnitTesting.Logger.LogInformation(string.Concat(methodBase.Name, " - Exit"));
|
EAFLoggingUnitTesting.Logger.LogInformation(string.Concat(methodBase.Name, " - Exit"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
[Ignore]
|
||||||
|
#endif
|
||||||
|
[TestMethod]
|
||||||
|
public void Development__v2_59_0__MESAFIBACKLOG__Violation()
|
||||||
|
{
|
||||||
|
string check = "*.json";
|
||||||
|
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
|
#endif
|
@ -51,8 +51,8 @@ public class MESAFIBACKLOG
|
|||||||
{
|
{
|
||||||
string check = "*.json";
|
string check = "*.json";
|
||||||
bool validatePDSF = false;
|
bool validatePDSF = false;
|
||||||
_MESAFIBACKLOG.Development__v2_59_0__MESAFIBACKLOG__Kanban();
|
|
||||||
MethodBase methodBase = new StackFrame().GetMethod();
|
MethodBase methodBase = new StackFrame().GetMethod();
|
||||||
|
_MESAFIBACKLOG.Development__v2_59_0__MESAFIBACKLOG__Kanban();
|
||||||
Assert.IsFalse(string.IsNullOrEmpty(_MESAFIBACKLOG.AdaptationTesting.TestContext.FullyQualifiedTestClassName));
|
Assert.IsFalse(string.IsNullOrEmpty(_MESAFIBACKLOG.AdaptationTesting.TestContext.FullyQualifiedTestClassName));
|
||||||
string[] variables = _MESAFIBACKLOG.AdaptationTesting.GetVariables(methodBase, check, validatePDSF);
|
string[] variables = _MESAFIBACKLOG.AdaptationTesting.GetVariables(methodBase, check, validatePDSF);
|
||||||
IFileRead fileRead = _MESAFIBACKLOG.AdaptationTesting.Get(methodBase, sourceFileLocation: variables[2], sourceFileFilter: variables[3], useCyclicalForDescription: false);
|
IFileRead fileRead = _MESAFIBACKLOG.AdaptationTesting.Get(methodBase, sourceFileLocation: variables[2], sourceFileFilter: variables[3], useCyclicalForDescription: false);
|
||||||
@ -141,8 +141,8 @@ public class MESAFIBACKLOG
|
|||||||
{
|
{
|
||||||
string check = "*.json";
|
string check = "*.json";
|
||||||
bool validatePDSF = false;
|
bool validatePDSF = false;
|
||||||
_MESAFIBACKLOG.Development__v2_59_0__MESAFIBACKLOG__Markdown();
|
|
||||||
MethodBase methodBase = new StackFrame().GetMethod();
|
MethodBase methodBase = new StackFrame().GetMethod();
|
||||||
|
_MESAFIBACKLOG.Development__v2_59_0__MESAFIBACKLOG__Markdown();
|
||||||
Assert.IsFalse(string.IsNullOrEmpty(_MESAFIBACKLOG.AdaptationTesting.TestContext.FullyQualifiedTestClassName));
|
Assert.IsFalse(string.IsNullOrEmpty(_MESAFIBACKLOG.AdaptationTesting.TestContext.FullyQualifiedTestClassName));
|
||||||
string[] variables = _MESAFIBACKLOG.AdaptationTesting.GetVariables(methodBase, check, validatePDSF);
|
string[] variables = _MESAFIBACKLOG.AdaptationTesting.GetVariables(methodBase, check, validatePDSF);
|
||||||
IFileRead fileRead = _MESAFIBACKLOG.AdaptationTesting.Get(methodBase, sourceFileLocation: variables[2], sourceFileFilter: variables[3], useCyclicalForDescription: false);
|
IFileRead fileRead = _MESAFIBACKLOG.AdaptationTesting.Get(methodBase, sourceFileLocation: variables[2], sourceFileFilter: variables[3], useCyclicalForDescription: false);
|
||||||
@ -150,19 +150,6 @@ public class MESAFIBACKLOG
|
|||||||
Assert.IsFalse(string.IsNullOrEmpty(extractResult?.Item1));
|
Assert.IsFalse(string.IsNullOrEmpty(extractResult?.Item1));
|
||||||
Assert.IsNotNull(extractResult.Item3);
|
Assert.IsNotNull(extractResult.Item3);
|
||||||
Assert.IsNotNull(extractResult.Item4);
|
Assert.IsNotNull(extractResult.Item4);
|
||||||
ReadOnlyDictionary<string, FileInfo> keyValuePairs = GetKeyValuePairs(extractResult.Item4);
|
|
||||||
Assert.IsTrue(keyValuePairs.ContainsKey("check-122508.json"));
|
|
||||||
Assert.IsTrue(keyValuePairs.ContainsKey("check-122514.json"));
|
|
||||||
Assert.IsTrue(keyValuePairs.ContainsKey("check-126169.json"));
|
|
||||||
Assert.IsTrue(keyValuePairs.ContainsKey("check-123066.json"));
|
|
||||||
Assert.IsTrue(keyValuePairs.ContainsKey("check-123067.json"));
|
|
||||||
Assert.IsTrue(keyValuePairs.ContainsKey("check-122517.json"));
|
|
||||||
Verify122508(keyValuePairs["check-122508.json"]);
|
|
||||||
Verify122514(keyValuePairs["check-122514.json"]);
|
|
||||||
Verify126169(keyValuePairs["check-126169.json"]);
|
|
||||||
Verify123066(keyValuePairs["check-123066.json"]);
|
|
||||||
Verify123067(keyValuePairs["check-123067.json"]);
|
|
||||||
Verify122517(keyValuePairs["check-122517.json"]);
|
|
||||||
NonThrowTryCatch();
|
NonThrowTryCatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,8 +213,8 @@ public class MESAFIBACKLOG
|
|||||||
{
|
{
|
||||||
string check = "*.json";
|
string check = "*.json";
|
||||||
bool validatePDSF = false;
|
bool validatePDSF = false;
|
||||||
_MESAFIBACKLOG.Development__v2_59_0__MESAFIBACKLOG__Markdown();
|
|
||||||
MethodBase methodBase = new StackFrame().GetMethod();
|
MethodBase methodBase = new StackFrame().GetMethod();
|
||||||
|
_MESAFIBACKLOG.Development__v2_59_0__MESAFIBACKLOG__Markdown();
|
||||||
Assert.IsFalse(string.IsNullOrEmpty(_MESAFIBACKLOG.AdaptationTesting.TestContext.FullyQualifiedTestClassName));
|
Assert.IsFalse(string.IsNullOrEmpty(_MESAFIBACKLOG.AdaptationTesting.TestContext.FullyQualifiedTestClassName));
|
||||||
string[] variables = _MESAFIBACKLOG.AdaptationTesting.GetVariables(methodBase, check, validatePDSF);
|
string[] variables = _MESAFIBACKLOG.AdaptationTesting.GetVariables(methodBase, check, validatePDSF);
|
||||||
IFileRead fileRead = _MESAFIBACKLOG.AdaptationTesting.Get(methodBase, sourceFileLocation: variables[2], sourceFileFilter: variables[3], useCyclicalForDescription: false);
|
IFileRead fileRead = _MESAFIBACKLOG.AdaptationTesting.Get(methodBase, sourceFileLocation: variables[2], sourceFileFilter: variables[3], useCyclicalForDescription: false);
|
||||||
@ -238,5 +225,38 @@ public class MESAFIBACKLOG
|
|||||||
NonThrowTryCatch();
|
NonThrowTryCatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
[Ignore]
|
||||||
|
#endif
|
||||||
|
[TestMethod]
|
||||||
|
public void Development__v2_59_0__MESAFIBACKLOG__Violation638779784153157287__Normal()
|
||||||
|
{
|
||||||
|
string check = "*.json";
|
||||||
|
bool validatePDSF = false;
|
||||||
|
MethodBase methodBase = new StackFrame().GetMethod();
|
||||||
|
_MESAFIBACKLOG.Development__v2_59_0__MESAFIBACKLOG__Violation();
|
||||||
|
Assert.IsFalse(string.IsNullOrEmpty(_MESAFIBACKLOG.AdaptationTesting.TestContext.FullyQualifiedTestClassName));
|
||||||
|
string[] variables = _MESAFIBACKLOG.AdaptationTesting.GetVariables(methodBase, check, validatePDSF);
|
||||||
|
IFileRead fileRead = _MESAFIBACKLOG.AdaptationTesting.Get(methodBase, sourceFileLocation: variables[2], sourceFileFilter: variables[3], useCyclicalForDescription: false);
|
||||||
|
Tuple<string, Test[], JsonElement[], List<FileInfo>> extractResult = fileRead.ReExtract();
|
||||||
|
Assert.IsFalse(string.IsNullOrEmpty(extractResult?.Item1));
|
||||||
|
Assert.IsNotNull(extractResult.Item3);
|
||||||
|
Assert.IsNotNull(extractResult.Item4);
|
||||||
|
ReadOnlyDictionary<string, FileInfo> keyValuePairs = GetKeyValuePairs(extractResult.Item4);
|
||||||
|
Assert.IsTrue(keyValuePairs.ContainsKey("check-122508.json"));
|
||||||
|
Assert.IsTrue(keyValuePairs.ContainsKey("check-122514.json"));
|
||||||
|
Assert.IsTrue(keyValuePairs.ContainsKey("check-126169.json"));
|
||||||
|
Assert.IsTrue(keyValuePairs.ContainsKey("check-123066.json"));
|
||||||
|
Assert.IsTrue(keyValuePairs.ContainsKey("check-123067.json"));
|
||||||
|
Assert.IsTrue(keyValuePairs.ContainsKey("check-122517.json"));
|
||||||
|
Verify122508(keyValuePairs["check-122508.json"]);
|
||||||
|
Verify122514(keyValuePairs["check-122514.json"]);
|
||||||
|
Verify126169(keyValuePairs["check-126169.json"]);
|
||||||
|
Verify123066(keyValuePairs["check-123066.json"]);
|
||||||
|
Verify123067(keyValuePairs["check-123067.json"]);
|
||||||
|
Verify122517(keyValuePairs["check-122517.json"]);
|
||||||
|
NonThrowTryCatch();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
File diff suppressed because it is too large
Load Diff
@ -157,6 +157,8 @@
|
|||||||
<Compile Include="Adaptation\FileHandlers\Priority\WorkItem.cs" />
|
<Compile Include="Adaptation\FileHandlers\Priority\WorkItem.cs" />
|
||||||
<Compile Include="Adaptation\FileHandlers\Processed\FileRead.cs" />
|
<Compile Include="Adaptation\FileHandlers\Processed\FileRead.cs" />
|
||||||
<Compile Include="Adaptation\FileHandlers\SPaCe\FileRead.cs" />
|
<Compile Include="Adaptation\FileHandlers\SPaCe\FileRead.cs" />
|
||||||
|
<Compile Include="Adaptation\FileHandlers\Violation\FileRead.cs" />
|
||||||
|
<Compile Include="Adaptation\FileHandlers\Violation\ProcessData.cs" />
|
||||||
<Compile Include="Adaptation\Ifx\Eaf\Common\Configuration\ConnectionSetting.cs" />
|
<Compile Include="Adaptation\Ifx\Eaf\Common\Configuration\ConnectionSetting.cs" />
|
||||||
<Compile Include="Adaptation\Ifx\Eaf\EquipmentConnector\File\Component\File.cs" />
|
<Compile Include="Adaptation\Ifx\Eaf\EquipmentConnector\File\Component\File.cs" />
|
||||||
<Compile Include="Adaptation\Ifx\Eaf\EquipmentConnector\File\Component\FilePathGenerator.cs" />
|
<Compile Include="Adaptation\Ifx\Eaf\EquipmentConnector\File\Component\FilePathGenerator.cs" />
|
||||||
@ -186,8 +188,8 @@
|
|||||||
<Compile Include="Adaptation\Shared\Metrology\WS.cs" />
|
<Compile Include="Adaptation\Shared\Metrology\WS.cs" />
|
||||||
<Compile Include="Adaptation\Shared\Metrology\WS.Results.cs" />
|
<Compile Include="Adaptation\Shared\Metrology\WS.Results.cs" />
|
||||||
<Compile Include="Adaptation\Shared\ParameterType.cs" />
|
<Compile Include="Adaptation\Shared\ParameterType.cs" />
|
||||||
<Compile Include="Adaptation\Shared\ProcessData.cs" />
|
|
||||||
<Compile Include="Adaptation\Shared\ProcessDataStandardFormat.cs" />
|
<Compile Include="Adaptation\Shared\ProcessDataStandardFormat.cs" />
|
||||||
|
<Compile Include="Adaptation\Shared\ProcessDataStandardFormatMapping.cs" />
|
||||||
<Compile Include="Adaptation\Shared\Properties\IDescription.cs" />
|
<Compile Include="Adaptation\Shared\Properties\IDescription.cs" />
|
||||||
<Compile Include="Adaptation\Shared\Properties\IFileRead.cs" />
|
<Compile Include="Adaptation\Shared\Properties\IFileRead.cs" />
|
||||||
<Compile Include="Adaptation\Shared\Properties\ILogistics.cs" />
|
<Compile Include="Adaptation\Shared\Properties\ILogistics.cs" />
|
||||||
|
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
|||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("2.58.0.0")]
|
[assembly: AssemblyVersion("2.59.0.0")]
|
||||||
[assembly: AssemblyFileVersion("2.58.0.0")]
|
[assembly: AssemblyFileVersion("2.59.0.0")]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user