Split violations from Markdown

ProcessDataStandardFormat over Tuple

MoveMatchingFiles to use ProcessDataStandardFormatMapping
This commit is contained in:
2025-03-28 12:01:05 -07:00
parent 40177bfb51
commit 2fc83bb54d
31 changed files with 3022 additions and 2268 deletions

View File

@ -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>());
_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();
if (_Logistics.FileInfo.Length < _MinFileLength)
results.Item4.Add(_Logistics.FileInfo);

View File

@ -120,15 +120,15 @@ public class FileRead : Shared.FileRead, IFileRead
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
{
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
ProcessData processData = ProcessDataStandardFormat.GetProcessData(reportFullPath);
_Logistics = new Logistics(reportFullPath, processData.Logistics);
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
SetFileParameterLotIDToLogisticsMID();
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processData);
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
List<Shared.Properties.IDescription> descriptions = GetDuplicatorDescriptions(jsonElements);
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
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;
}

View File

@ -120,9 +120,10 @@ public class FileRead : Shared.FileRead, IFileRead
if (dateTime == DateTime.MinValue)
throw new ArgumentNullException(nameof(dateTime));
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 weekDirectory = $"{_Logistics.DateTimeFromSequence:yyyy}_Week_{weekOfYear}{@"\"}{_Logistics.DateTimeFromSequence:yyyy-MM-dd}";
string destinationArchiveDirectory = Path.Combine(_JobIdArchiveParentDirectory, _Logistics.JobID, weekDirectory);
string weekDirectory = $"{_Logistics.DateTimeFromSequence:yyyy}_Week_{weekOfYear}";
string destinationArchiveDirectory = Path.Combine(_JobIdArchiveParentDirectory, _Logistics.JobID, weekDirectory, day);
if (!Directory.Exists(destinationArchiveDirectory))
_ = Directory.CreateDirectory(destinationArchiveDirectory);
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)
{
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
ProcessData processData = ProcessDataStandardFormat.GetProcessData(reportFullPath);
_Logistics = new Logistics(reportFullPath, processData.Logistics);
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
SetFileParameterLotIDToLogisticsMID();
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processData);
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
List<Shared.Properties.IDescription> descriptions = GetDuplicatorDescriptions(jsonElements);
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
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;
}

View File

@ -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(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(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")
};
return result;

View File

@ -119,15 +119,15 @@ public class FileRead : Shared.FileRead, IFileRead
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
{
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
ProcessData processData = ProcessDataStandardFormat.GetProcessData(reportFullPath);
_Logistics = new Logistics(reportFullPath, processData.Logistics);
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
SetFileParameterLotIDToLogisticsMID();
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processData);
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
List<Shared.Properties.IDescription> descriptions = GetDuplicatorDescriptions(jsonElements);
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
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;
}

View File

@ -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>());
_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();
if (_Logistics.FileInfo.Length < _MinFileLength)
results.Item4.Add(_Logistics.FileInfo);

View File

@ -13,6 +13,8 @@ using System.Text.Json.Serialization;
namespace Adaptation.FileHandlers.Kanban;
#nullable enable
public class ProcessData : IProcessData
{
@ -22,125 +24,25 @@ public class ProcessData : IProcessData
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) =>
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);
#nullable enable
internal static List<Description> GetDescriptions(JsonElement[] jsonElements)
public ProcessData(IFileRead fileRead, Logistics logistics, Calendar calendar, string targetFileLocation, string url, List<FileInfo> fileInfoCollection)
{
List<Description> results = new();
Description? description;
JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString };
foreach (JsonElement jsonElement in jsonElements)
if (fileRead.IsEAFHosted)
{
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)
{
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)
{
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)
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);
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 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;
}
}

View File

@ -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>());
_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();
if (_Logistics.FileInfo.Length < _MinFileLength)
results.Item4.Add(_Logistics.FileInfo);

View File

@ -13,6 +13,8 @@ using System.Text.Json.Serialization;
namespace Adaptation.FileHandlers.Markdown;
#nullable enable
public class ProcessData : IProcessData
{
@ -22,38 +24,46 @@ public class ProcessData : IProcessData
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) =>
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);
#nullable enable
internal static List<Description> GetDescriptions(JsonElement[] jsonElements)
public ProcessData(IFileRead fileRead, Logistics logistics, string targetFileLocation, string url, ReadOnlyCollection<string> workItemTypes, List<FileInfo> fileInfoCollection)
{
List<Description> results = new();
Description? description;
JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString };
foreach (JsonElement jsonElement in jsonElements)
if (fileRead.IsEAFHosted)
{
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)
@ -83,13 +93,11 @@ public class ProcessData : IProcessData
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" });
messages.AddRange(WriteFile(fileRead, destinationDirectory, fileInfoCollection, records, "records"));
messages.AddRange(WriteWithPartentsFile(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, bugFeatureWorkItemTypes, "bugs-features-with-parents"));
messages.AddRange(WriteWithParentsFile(fileRead, destinationDirectory, fileInfoCollection, records, bugUserStoryWorkItemTypes, "bugs-user-stories-with-parents"));
foreach (string workItemType in workItemTypes)
{
lines.Clear();
@ -100,98 +108,10 @@ public class ProcessData : IProcessData
WriteFiles(fileRead, destinationDirectory, fileInfoCollection, new(lines), results, workItemType);
_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)
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)
{
ReadOnlyDictionary<int, Record> results;
@ -202,6 +122,74 @@ public class ProcessData : IProcessData
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)
{
string? result;
@ -221,39 +209,22 @@ public class ProcessData : IProcessData
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? 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> 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)
string line;
spaces.Add('\t');
WorkItem workItem;
if (record.Children is not null)
{
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);
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);
}
}
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);
spaces.RemoveAt(0);
}
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)
{
string result;
@ -368,485 +288,21 @@ public class ProcessData : IProcessData
private static string GetClosed(WorkItem workItem) =>
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 (!workItemTypes.Contains(r.WorkItem.WorkItemType))
continue;
results.Add(r);
FilterChildren(workItemTypes, r, results);
}
if (jsonElement.ValueKind != JsonValueKind.Object)
throw new Exception();
description = JsonSerializer.Deserialize<Description>(jsonElement.ToString(), jsonSerializerOptions);
if (description is null)
continue;
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;
}
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);
}
}

View File

@ -5,16 +5,68 @@ using Adaptation.Shared.Duplicator;
using Adaptation.Shared.Methods;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading;
namespace Adaptation.FileHandlers.MoveMatchingFiles;
#nullable enable
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) :
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);
}
void IFileRead.WaitForThread() => WaitForThread(thread: null, threadExceptions: null);
void IFileRead.WaitForThread() =>
WaitForThread(thread: null, threadExceptions: null);
string IFileRead.GetEventDescription()
{
@ -88,7 +141,7 @@ public class FileRead : Shared.FileRead, IFileRead
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);
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)
WritePDSF(this, results.Item3);
UpdateLastTicksDuration(DateTime.Now.Ticks - dateTime.Ticks);
@ -104,7 +157,69 @@ public class FileRead : Shared.FileRead, IFileRead
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();
string[] directories = Directory.GetDirectories(parentDirectory, "*", SearchOption.TopDirectoryOnly);
@ -115,10 +230,137 @@ public class FileRead : Shared.FileRead, IFileRead
results.Add(directory);
}
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;
}
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();
string[] found;
@ -137,129 +379,7 @@ public class FileRead : Shared.FileRead, IFileRead
break;
}
}
return results;
}
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;
return results.AsReadOnly();
}
}

View File

@ -118,15 +118,15 @@ public class FileRead : Shared.FileRead, IFileRead
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
{
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
ProcessData processData = ProcessDataStandardFormat.GetProcessData(reportFullPath);
_Logistics = new Logistics(reportFullPath, processData.Logistics);
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
SetFileParameterLotIDToLogisticsMID();
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processData);
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
List<Description> descriptions = json.ProcessData.GetDescriptions(jsonElements);
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
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;
}

View File

@ -129,15 +129,15 @@ public class FileRead : Shared.FileRead, IFileRead
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
{
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
ProcessData processData = ProcessDataStandardFormat.GetProcessData(reportFullPath);
_Logistics = new Logistics(reportFullPath, processData.Logistics);
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
SetFileParameterLotIDToLogisticsMID();
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processData);
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
List<Description> descriptions = json.ProcessData.GetDescriptions(jsonElements);
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
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;
}

View File

@ -146,15 +146,15 @@ public class FileRead : Shared.FileRead, IFileRead
if (dateTime == DateTime.MinValue)
throw new ArgumentNullException(nameof(dateTime));
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
ProcessData processData = ProcessDataStandardFormat.GetProcessData(reportFullPath);
_Logistics = new Logistics(reportFullPath, processData.Logistics);
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
SetFileParameterLotIDToLogisticsMID();
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processData);
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
List<Description> descriptions = json.ProcessData.GetDescriptions(jsonElements);
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
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;
}

View File

@ -131,7 +131,9 @@ public class FileRead : Shared.FileRead, IFileRead
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
if (dateTime == DateTime.MinValue)
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>());
return results;
}

View File

@ -143,13 +143,13 @@ public class FileRead : Shared.FileRead, IFileRead
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
{
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
ProcessData processData = ProcessDataStandardFormat.GetProcessData(reportFullPath);
_Logistics = new Logistics(reportFullPath, processData.Logistics);
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
SetFileParameterLotIDToLogisticsMID();
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processData);
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
List<Description> descriptions = json.ProcessData.GetDescriptions(jsonElements);
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)
DirectoryMove(reportFullPath, dateTime, descriptions);
else if (!_IsEAFHosted)

View File

@ -117,15 +117,15 @@ public class FileRead : Shared.FileRead, IFileRead
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
{
Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
ProcessData processData = ProcessDataStandardFormat.GetProcessData(reportFullPath);
_Logistics = new Logistics(reportFullPath, processData.Logistics);
ProcessDataStandardFormat processDataStandardFormat = ProcessDataStandardFormat.GetProcessDataStandardFormat(reportFullPath);
_Logistics = new Logistics(reportFullPath, processDataStandardFormat);
SetFileParameterLotIDToLogisticsMID();
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processData);
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
List<Shared.Properties.IDescription> descriptions = GetDuplicatorDescriptions(jsonElements);
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
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;
}

View 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;
}
}

View 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;
}
}

View File

@ -358,7 +358,9 @@ public class FileRead : Shared.FileRead, IFileRead
private Tuple<string, Test[], JsonElement[], List<FileInfo>> GetExtractResult(string reportFullPath, DateTime dateTime)
{
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)
MoveJson(reportFullPath, dateTime);
results = new(_Logistics.Logistics1[0], Array.Empty<Test>(), Array.Empty<JsonElement>(), new List<FileInfo>());