From 6581945127d6a4e83065e0e73068637497479420 Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Sun, 13 Oct 2024 10:40:15 -0700 Subject: [PATCH] Created tests --- .../DownloadWorkItems/FileRead.cs | 3 +- Adaptation/FileHandlers/Kanban/FileRead.cs | 3 +- Adaptation/FileHandlers/Markdown/FileRead.cs | 495 +----------- .../FileHandlers/Markdown/ProcessData.cs | 723 ++++++++++++++++++ Adaptation/FileHandlers/json/FileRead.cs | 3 +- Adaptation/FileHandlers/json/ProcessData.cs | 17 +- .../FileHandlers/json/WorkItems/WorkItem.cs | 2 + Adaptation/MESAFIBACKLOG.Tests.csproj | 24 +- Adaptation/Shared/Test.cs | 3 +- .../Production/v2.57.0/MESAFIBACKLOG.cs | 69 ++ MESAFIBACKLOG.csproj | 1 + 11 files changed, 831 insertions(+), 512 deletions(-) create mode 100644 Adaptation/FileHandlers/Markdown/ProcessData.cs diff --git a/Adaptation/FileHandlers/DownloadWorkItems/FileRead.cs b/Adaptation/FileHandlers/DownloadWorkItems/FileRead.cs index 42b233e..c3110b1 100644 --- a/Adaptation/FileHandlers/DownloadWorkItems/FileRead.cs +++ b/Adaptation/FileHandlers/DownloadWorkItems/FileRead.cs @@ -56,7 +56,8 @@ public class FileRead : Shared.FileRead, IFileRead _HttpClient.DefaultRequestHeaders.Authorization = new("Basic", base64); _HttpClient.DefaultRequestHeaders.Accept.Add(mediaTypeWithQualityHeaderValue); _BasePage = basePage; - NestExistingFiles(_FileConnectorConfiguration); + if (_IsEAFHosted) + NestExistingFiles(_FileConnectorConfiguration); if (!Debugger.IsAttached && fileConnectorConfiguration.PreProcessingMode != FileConnectorConfiguration.PreProcessingModeEnum.Process) _Timer = new Timer(Callback, null, (int)(fileConnectorConfiguration.FileScanningIntervalInSeconds * 1000), Timeout.Infinite); else diff --git a/Adaptation/FileHandlers/Kanban/FileRead.cs b/Adaptation/FileHandlers/Kanban/FileRead.cs index cfe4a4b..9ab59ba 100644 --- a/Adaptation/FileHandlers/Kanban/FileRead.cs +++ b/Adaptation/FileHandlers/Kanban/FileRead.cs @@ -42,7 +42,8 @@ public class FileRead : Shared.FileRead, IFileRead foreach (ModelObjectParameterDefinition modelObjectParameterDefinition in FrontMatterLinesDefinitions) FrontMatterLines.Add(modelObjectParameterDefinition.Value); _FrontMatterLines = new(FrontMatterLines); - NestExistingFiles(_FileConnectorConfiguration); + if (_IsEAFHosted) + NestExistingFiles(_FileConnectorConfiguration); } void IFileRead.Move(Tuple> extractResults, Exception exception) => Move(extractResults); diff --git a/Adaptation/FileHandlers/Markdown/FileRead.cs b/Adaptation/FileHandlers/Markdown/FileRead.cs index 2fb2d95..0332b1d 100644 --- a/Adaptation/FileHandlers/Markdown/FileRead.cs +++ b/Adaptation/FileHandlers/Markdown/FileRead.cs @@ -1,5 +1,4 @@ using Adaptation.Eaf.Management.ConfigurationData.CellAutomation; -using Adaptation.FileHandlers.json.WorkItems; using Adaptation.Ifx.Eaf.EquipmentConnector.File.Configuration; using Adaptation.Shared; using Adaptation.Shared.Duplicator; @@ -8,7 +7,6 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; -using System.Linq; using System.Text.Json; namespace Adaptation.FileHandlers.Markdown; @@ -16,6 +14,7 @@ namespace Adaptation.FileHandlers.Markdown; public class FileRead : Shared.FileRead, IFileRead { + private long? _TickOffset; private readonly string _URL; private readonly ReadOnlyCollection _WorkItemTypes; @@ -35,7 +34,8 @@ public class FileRead : Shared.FileRead, IFileRead _URL = GetPropertyValue(cellInstanceConnectionName, modelObjectParameters, $"{cellInstanceNamed}.URL"); string workItemTypes = GetPropertyValue(cellInstanceConnectionName, modelObjectParameters, $"{cellInstanceNamed}.WorkItemTypes"); _WorkItemTypes = new(workItemTypes.Split('|')); - NestExistingFiles(_FileConnectorConfiguration); + if (_IsEAFHosted) + NestExistingFiles(_FileConnectorConfiguration); } void IFileRead.Move(Tuple> extractResults, Exception exception) => Move(extractResults); @@ -103,486 +103,21 @@ public class FileRead : Shared.FileRead, IFileRead return results; } -#nullable enable - - private static ReadOnlyDictionary GetWorkItems(ReadOnlyCollection workItems) - { - Dictionary results = new(); - foreach (WorkItem workItem in workItems) - results.Add(workItem.Id, workItem); - return new(results); - } - - private static int? GetIdFromUrlIfChild(Relation relation) - { - int? result; - string[] segments = relation?.Attributes is null || relation.Attributes.Name != "Child" ? Array.Empty() : relation.URL.Split('/'); - if (segments.Length < 2) - result = null; - else - { - if (!int.TryParse(segments[segments.Length - 1], out int id)) - result = null; - else - result = id; - } - return result; - } - - private static ReadOnlyCollection GetKeyValuePairs(ReadOnlyDictionary workItems, WorkItem workItem) - { - List results = new(); - int? childId; - WorkItem? childWorkItem; - WorkItem? parentWorkItem; - List collection = new(); - ReadOnlyCollection records; - if (workItem.Relations is not null && workItem.Relations.Length > 0) - { - collection.Clear(); - foreach (Relation relation in workItem.Relations) - { - childId = GetIdFromUrlIfChild(relation); - if (childId is null || !workItems.TryGetValue(childId.Value, out childWorkItem)) - continue; - collection.Add(childWorkItem); - } - collection = (from l in collection orderby l.State != "Closed", l.Id select l).ToList(); - foreach (WorkItem item in collection) - { - if (item.Parent is null) - parentWorkItem = null; - else - _ = workItems.TryGetValue(item.Parent.Value, out parentWorkItem); - records = GetKeyValuePairs(workItems, item); - results.Add(new(item, parentWorkItem, records)); - } - } - return new(results); - } - - private static ReadOnlyCollection GetRecords(ReadOnlyDictionary workItems) - { - List results = new(); - WorkItem? parentWorkItem; - ReadOnlyCollection records; - foreach (KeyValuePair keyValuePair in workItems) - { - if (keyValuePair.Value.Parent is null) - parentWorkItem = null; - else - _ = workItems.TryGetValue(keyValuePair.Value.Parent.Value, out parentWorkItem); - records = GetKeyValuePairs(workItems, keyValuePair.Value); - results.Add(new(keyValuePair.Value, parentWorkItem, records)); - - } - return new(results); - } - - private static string GetClosed(WorkItem workItem) - { - string result = workItem.State != "Closed" ? "[ ]" : "[x]"; - return result; - } - - private static string GetLine(List spaces, WorkItem workItem, Record record, bool condensed, bool sprintOnly) => - sprintOnly ? $"\t- [ ] {workItem.IterationPath}" : - condensed ? $"{new string(spaces.Skip(1).ToArray())}- {GetClosed(workItem)} {record.WorkItem.Id} - {workItem.Title}" : - $"{new string(spaces.Skip(1).ToArray())}- {GetClosed(workItem)} {record.WorkItem.Id} - {workItem.Title} ~~~ {workItem.AssignedTo} - {workItem.IterationPath.Replace('\\', '-')} - {workItem.CreatedDate} --- {workItem.ClosedDate}"; - - private static void AppendLines(List spaces, List lines, Record record, bool condensed, bool sprintOnly) - { - string line; - spaces.Add('\t'); - WorkItem workItem; - 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 void AppendLines(string url, List spaces, List lines, ReadOnlyCollection records, string workItemType) - { - List results = new(); - WorkItem workItem; - string? maxIterationPath; - List distinct = new(); - foreach (Record record in records) - { - workItem = record.WorkItem; - // if (record.WorkItem.Id != 109724) - // continue; - if (workItem.WorkItemType != workItemType) - continue; - results.Add($"## {workItem.AssignedTo} - {workItem.Id} - {workItem.Title}"); - results.Add(string.Empty); - results.Add($"- [{workItem.Id}]({url}{workItem.Id})"); - if (record.Children.Count == 0) - results.Add(string.Empty); - else - { - AppendLines(spaces, results, record, condensed: true, sprintOnly: false); - results.Add(string.Empty); - distinct.Clear(); - AppendLines(spaces, distinct, record, condensed: false, sprintOnly: true); - if (distinct.Count > 1) - { - results.Add($"## Distinct Iteration Path(s) - {workItem.WorkItemType} - {workItem.AssignedTo} - {workItem.Id} - {workItem.Title} - {workItem.IterationPath}"); - results.Add(string.Empty); - results.Add($"- [{workItem.Id}]({url}{workItem.Id})"); - distinct.Sort(); - distinct = (from l in distinct select l.Trim()).Distinct().ToList(); - results.AddRange(distinct); - results.Add(string.Empty); - maxIterationPath = distinct.Max(); - if (!string.IsNullOrEmpty(maxIterationPath) && maxIterationPath.Contains("] ") && maxIterationPath.Split(']')[1].Trim() != workItem.IterationPath) - { - results.Add($"### Sync to Distinct Max Iteration Path => {maxIterationPath} - {workItem.Id} - {workItem.Title}"); - results.Add(string.Empty); - } - } - results.Add($"## Extended - {workItem.Id} - {workItem.Title}"); - results.Add(string.Empty); - AppendLines(spaces, results, record, condensed: false, sprintOnly: false); - results.Add(string.Empty); - } - lines.AddRange(results); - results.Clear(); - } - } - - private static void WriteFiles(string destinationDirectory, ReadOnlyCollection records, string fileName) - { - 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); - } - - private static void WriteFiles(string destinationDirectory, ReadOnlyCollection lines, ReadOnlyCollection workItems, string fileName) - { - string text = string.Join(Environment.NewLine, lines); - string markdownFile = Path.Combine(destinationDirectory, $"{fileName}.md"); - string textOld = !File.Exists(markdownFile) ? string.Empty : File.ReadAllText(markdownFile); - if (text != textOld) - File.WriteAllText(markdownFile, text); - string html = CommonMark.CommonMarkConverter.Convert(text).Replace(" FilterChildren(Record record, ReadOnlyCollection workItemTypes) - { - List results = new(); - WorkItem workItem; - foreach (Record item in record.Children) - { - workItem = item.WorkItem; - if (!workItemTypes.Contains(workItem.WorkItemType)) - continue; - results.Add(workItem); - } - return new(results); - } - - private static string? GetMaxIterationPath(ReadOnlyCollection workItems) - { - string? result; - List results = new(); - foreach (WorkItem workItem in workItems) - { - if (results.Contains(workItem.IterationPath)) - continue; - results.Add(workItem.IterationPath); - } - result = results.Count == 0 ? null : results.Max(); - return result; - } - - private static ReadOnlyCollection FeatureCheckIterationPath122508(string url, List lines, ReadOnlyCollection workItemTypes, ReadOnlyCollection records, string workItemType) - { - List results = new(); - WorkItem workItem; - string? maxIterationPath; - List collection = new(); - ReadOnlyCollection childrenWorkItems; - foreach (Record record in records) - { - workItem = record.WorkItem; - if (workItem.WorkItemType != workItemType) - continue; - collection.Clear(); - if (record.Children.Count == 0) - continue; - childrenWorkItems = FilterChildren(record, workItemTypes); - maxIterationPath = GetMaxIterationPath(childrenWorkItems); - if (string.IsNullOrEmpty(maxIterationPath) || workItem.IterationPath == maxIterationPath) - continue; - collection.Add($"## {workItem.AssignedTo} - {workItem.Id} - {workItem.Title}"); - collection.Add(string.Empty); - collection.Add($"- [ ] [{workItem.Id}]({url}{workItem.Id}) => {workItem.IterationPath} != {maxIterationPath}"); - collection.Add(string.Empty); - lines.AddRange(collection); - results.Add(WorkItem.Get(workItem, $"IterationPath:{workItem.Id};{workItem.IterationPath} != {maxIterationPath}")); - } - return new(results); - } - - private static ReadOnlyCollection GetWorkItemsNotMatching(string tags, ReadOnlyCollection workItems) - { - List results = new(); - string[] segments; - string[] parentTags = tags.Split(';'); - foreach (WorkItem workItem in workItems) - { - segments = tags.Split(';'); - if (segments.Length > 0 && parentTags.Any(l => segments.Contains(l))) - continue; - results.Add(workItem); - } - return new(results); - } - - private static ReadOnlyCollection FeatureCheckTag122514(string url, List lines, ReadOnlyCollection workItemTypes, ReadOnlyCollection records, string workItemType) - { - List results = new(); - WorkItem workItem; - List collection = new(); - List violations = new(); - ReadOnlyCollection childrenWorkItems; - ReadOnlyCollection workItemsNotMatching; - foreach (Record record in records) - { - workItem = record.WorkItem; - if (workItem.WorkItemType != workItemType) - continue; - collection.Clear(); - violations.Clear(); - if (record.Children.Count == 0) - continue; - if (string.IsNullOrEmpty(workItem.Tags)) - workItemsNotMatching = new(new WorkItem[] { workItem }); - else - { - childrenWorkItems = FilterChildren(record, workItemTypes); - workItemsNotMatching = GetWorkItemsNotMatching(workItem.Tags, childrenWorkItems); - if (!string.IsNullOrEmpty(workItem.Tags) && workItemsNotMatching.Count == 0) - continue; - } - collection.Add($"## {workItem.AssignedTo} - {workItem.Id} - {workItem.Title}"); - collection.Add(string.Empty); - foreach (WorkItem item in workItemsNotMatching) - collection.Add($"- [ ] [{item}]({url}{item}) {nameof(workItem.Tags)} != {workItem.Tags}"); - collection.Add(string.Empty); - lines.AddRange(collection); - violations.Add($"Tag:{workItem.Tags};"); - foreach (WorkItem item in workItemsNotMatching) - violations.Add($"{item.Id}:{item.Tags};"); - results.Add(WorkItem.Get(workItem, string.Join(" ", violations))); - } - return new(results); - } - - private static ReadOnlyCollection GetWorkItemsNotMatching(int? priority, ReadOnlyCollection workItems) - { - List results = new(); - foreach (WorkItem workItem in workItems) - { - if (workItem.Priority == priority) - continue; - results.Add(workItem); - } - return new(results); - } - - private static ReadOnlyCollection FeatureCheckPriority126169(string url, List lines, ReadOnlyCollection workItemTypes, ReadOnlyCollection records, string workItemType) - { - List results = new(); - WorkItem workItem; - List collection = new(); - List violations = new(); - ReadOnlyCollection childrenWorkItems; - ReadOnlyCollection workItemsNotMatching; - foreach (Record record in records) - { - workItem = record.WorkItem; - if (workItem.WorkItemType != workItemType) - continue; - collection.Clear(); - violations.Clear(); - if (record.Children.Count == 0) - continue; - childrenWorkItems = FilterChildren(record, workItemTypes); - workItemsNotMatching = GetWorkItemsNotMatching(workItem.Priority, childrenWorkItems); - if (workItemsNotMatching.Count == 0) - continue; - collection.Add($"## {workItem.AssignedTo} - {workItem.Id} - {workItem.Title}"); - collection.Add(string.Empty); - collection.Add($"- [{workItem.Id}]({url}{workItem.Id})"); - foreach (WorkItem item in workItemsNotMatching) - collection.Add($"- [ ] [{item.Id}]({url}{item.Id}) {nameof(workItem.Priority)} != {workItem.Priority}"); - collection.Add(string.Empty); - lines.AddRange(collection); - violations.Add($"Priority:{workItem.Priority};"); - foreach (WorkItem item in workItemsNotMatching) - violations.Add($"{item.Id}:{item.Priority};"); - results.Add(WorkItem.Get(workItem, string.Join(" ", violations))); - } - return new(results); - } - - private static ReadOnlyCollection GetWorkItemsNotMatching(int state, ReadOnlyCollection workItems) - { - List results = new(); - int check; - List> collection = new(); - foreach (WorkItem workItem in workItems) - { - check = GetState(workItem); - if (check != state) - continue; - collection.Add(new(check, workItem)); - } - foreach (KeyValuePair 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 FeatureCheckState123066(string url, List lines, ReadOnlyCollection workItemTypes, ReadOnlyCollection records, string workItemType) - { - List results = new(); - int state; - WorkItem workItem; - List collection = new(); - List violations = new(); - ReadOnlyCollection childrenWorkItems; - ReadOnlyCollection workItemsNotMatching; - foreach (Record record in records) - { - workItem = record.WorkItem; - if (workItem.WorkItemType != workItemType) - continue; - collection.Clear(); - violations.Clear(); - if (record.Children.Count == 0) - continue; - state = GetState(workItem); - childrenWorkItems = FilterChildren(record, workItemTypes); - workItemsNotMatching = GetWorkItemsNotMatching(state, childrenWorkItems); - if (workItemsNotMatching.Count == 0) - continue; - collection.Add($"## {workItem.AssignedTo} - {workItem.Id} - {workItem.Title}"); - collection.Add(string.Empty); - collection.Add($"- [{workItem.Id}]({url}{workItem.Id})"); - foreach (WorkItem item in workItemsNotMatching) - collection.Add($"- [ ] [{item.Id}]({url}{item.Id}) {nameof(workItem.State)} != {workItem.State}"); - collection.Add(string.Empty); - lines.AddRange(collection); - violations.Add($"State:{workItem.State};"); - foreach (WorkItem item in workItemsNotMatching) - violations.Add($"{item.Id}:{item.State};"); - results.Add(WorkItem.Get(workItem, string.Join(" ", violations))); - } - return new(results); - } - - private static void WriteFiles(FileConnectorConfiguration fileConnectorConfiguration, string url, ReadOnlyCollection workItemTypes, ReadOnlyCollection workItems) - { - List spaces = new(); - List lines = new(); - ReadOnlyCollection results; - ReadOnlyDictionary collection = GetWorkItems(workItems); - ReadOnlyCollection records = GetRecords(collection); - ReadOnlyCollection bugUserStoryWorkItemTypes = new(new string[] { "Bug", "User Story" }); - ReadOnlyCollection bugUserStoryTaskWorkItemTypes = new(new string[] { "Bug", "User Story", "Task" }); - if (!Directory.Exists(fileConnectorConfiguration.TargetFileLocation)) - _ = Directory.CreateDirectory(fileConnectorConfiguration.TargetFileLocation); - WriteFiles(fileConnectorConfiguration.TargetFileLocation, records, "with-parents"); - foreach (string workItemType in workItemTypes) - { - lines.Clear(); - lines.Add($"# {workItemType}"); - lines.Add(string.Empty); - AppendLines(url, spaces, lines, records, workItemType); - results = new(Array.Empty()); - WriteFiles(fileConnectorConfiguration.TargetFileLocation, new(lines), results, workItemType); - } - { - lines.Clear(); - string workItemType = "Feature"; - lines.Add($"# {nameof(FeatureCheckIterationPath122508)}"); - lines.Add(string.Empty); - results = FeatureCheckIterationPath122508(url, lines, bugUserStoryTaskWorkItemTypes, records, workItemType); - WriteFiles(fileConnectorConfiguration.TargetFileLocation, new(lines), results, "check-122508"); - } - { - lines.Clear(); - string workItemType = "Feature"; - lines.Add($"# {nameof(FeatureCheckTag122514)}"); - lines.Add(string.Empty); - results = FeatureCheckTag122514(url, lines, bugUserStoryWorkItemTypes, records, workItemType); - WriteFiles(fileConnectorConfiguration.TargetFileLocation, new(lines), results, "check-122514"); - } - { - lines.Clear(); - string workItemType = "Feature"; - lines.Add($"# {nameof(FeatureCheckPriority126169)}"); - lines.Add(string.Empty); - results = FeatureCheckPriority126169(url, lines, bugUserStoryWorkItemTypes, records, workItemType); - WriteFiles(fileConnectorConfiguration.TargetFileLocation, new(lines), results, "check-126169"); - } - { - lines.Clear(); - string workItemType = "Feature"; - lines.Add($"# {nameof(FeatureCheckState123066)}"); - lines.Add(string.Empty); - results = FeatureCheckState123066(url, lines, bugUserStoryTaskWorkItemTypes, records, workItemType); - WriteFiles(fileConnectorConfiguration.TargetFileLocation, new(lines), results, "check-123066"); - } - } - -#pragma warning disable IDE0060 - private void WriteFiles(string reportFullPath, DateTime dateTime) -#pragma warning restore IDE0060 - { - string json = File.ReadAllText(reportFullPath); - WorkItem[]? workItems = JsonSerializer.Deserialize(json); - if (workItems is null) - throw new Exception(nameof(workItems)); - if (workItems.Length > 0) - WriteFiles(_FileConnectorConfiguration, _URL, _WorkItemTypes, new(workItems)); - } - private Tuple> GetExtractResult(string reportFullPath, DateTime dateTime) { - Tuple> results; + Tuple> results = new(string.Empty, null, null, new List()); + _TickOffset ??= 0; // new FileInfo(reportFullPath).LastWriteTime.Ticks - dateTime.Ticks; _Logistics = new Logistics(reportFullPath, $"LOGISTICS_1{'\t'}A_JOBID={"BACKLOG"};A_MES_ENTITY={"BACKLOG"};"); - if (_IsEAFHosted) - WriteFiles(reportFullPath, dateTime); - results = new(_Logistics.Logistics1[0], Array.Empty(), Array.Empty(), new List()); + 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) + throw new Exception(string.Concat("B) No Data - ", dateTime.Ticks)); + results = iProcessData.GetResults(this, _Logistics, results.Item4); + } return results; } diff --git a/Adaptation/FileHandlers/Markdown/ProcessData.cs b/Adaptation/FileHandlers/Markdown/ProcessData.cs new file mode 100644 index 0000000..1125392 --- /dev/null +++ b/Adaptation/FileHandlers/Markdown/ProcessData.cs @@ -0,0 +1,723 @@ +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.Markdown; + +public class ProcessData : IProcessData +{ + + private readonly List _Details; + + List Shared.Properties.IProcessData.Details => _Details; + + private readonly ILog _Log; + + public ProcessData(IFileRead fileRead, Logistics logistics, string targetFileLocation, string url, ReadOnlyCollection workItemTypes, List fileInfoCollection) + { + if (fileRead.IsEAFHosted) + { } + fileInfoCollection.Clear(); + _Details = new List(); + _Log = LogManager.GetLogger(typeof(ProcessData)); + WriteFiles(fileRead, logistics, url, workItemTypes, targetFileLocation, fileInfoCollection); + } + + string IProcessData.GetCurrentReactor(IFileRead fileRead, Logistics logistics, Dictionary reactors) => + throw new Exception(string.Concat("See ", nameof(WriteFiles))); + + Tuple> IProcessData.GetResults(IFileRead fileRead, Logistics logistics, List fileInfoCollection) => + new(logistics.Logistics1[0], Array.Empty(), Array.Empty(), fileInfoCollection); + +#nullable enable + + internal static List GetDescriptions(JsonElement[] jsonElements) + { + List 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(jsonElement.ToString(), jsonSerializerOptions); + if (description is null) + continue; + results.Add(description); + } + return results; + } + + private void WriteFiles(IFileRead fileRead, Logistics logistics, string url, ReadOnlyCollection workItemTypes, string destinationDirectory, List fileInfoCollection) + { + string json = File.ReadAllText(logistics.ReportFullPath); + WorkItem[]? workItems = JsonSerializer.Deserialize(json); + if (workItems is null) + throw new Exception(nameof(workItems)); + List spaces = new(); + List lines = new(); + ReadOnlyCollection results; + ReadOnlyDictionary keyValuePairs = GetWorkItems(workItems); + WriteFileStructure(destinationDirectory, keyValuePairs); + ReadOnlyCollection records = new(keyValuePairs.Values.ToArray()); + ReadOnlyCollection bugUserStoryWorkItemTypes = new(new string[] { "Bug", "User Story" }); + ReadOnlyCollection bugUserStoryTaskWorkItemTypes = new(new string[] { "Bug", "User Story", "Task" }); + if (!Directory.Exists(destinationDirectory)) + _ = Directory.CreateDirectory(destinationDirectory); + WriteFiles(fileRead, destinationDirectory, fileInfoCollection, records, "with-parents"); + foreach (string workItemType in workItemTypes) + { + lines.Clear(); + lines.Add($"# {workItemType}"); + lines.Add(string.Empty); + AppendLines(url, spaces, lines, records, workItemType); + results = new(Array.Empty()); + 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, records, 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, records, 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, records, 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, records, 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, records, workItemType); + WriteFiles(fileRead, destinationDirectory, fileInfoCollection, new(lines), results, "check-123067"); + _Details.Add(results); + } + } + + private static void WriteFiles(IFileRead fileRead, string destinationDirectory, List fileInfoCollection, ReadOnlyCollection lines, ReadOnlyCollection workItems, 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(" GetWorkItems(WorkItem[] workItems) + { + ReadOnlyDictionary results; + Dictionary keyValuePairs = new(); + foreach (WorkItem workItem in workItems) + keyValuePairs.Add(workItem.Id, workItem); + results = GetKeyValuePairs(new(keyValuePairs)); + return results; + } + + private static void WriteFileStructure(string destinationDirectory, ReadOnlyDictionary keyValuePairs) + { + ReadOnlyCollection collection = GetDirectories(destinationDirectory, keyValuePairs); + foreach (string directory in collection) + { + if (directory.Length > 222) + continue; + if (!Directory.Exists(directory)) + _ = Directory.CreateDirectory(directory); + } + } + + private static void WriteFiles(IFileRead fileRead, string destinationDirectory, List fileInfoCollection, ReadOnlyCollection records, string fileName) + { + 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 void AppendLines(string url, List spaces, List lines, ReadOnlyCollection records, string workItemType) + { + List results = new(); + string? maxIterationPath; + List distinct = new(); + foreach (Record record in records) + { + // if (record.WorkItem.Id != 109724) + // continue; + if (record.WorkItem.WorkItemType != workItemType) + continue; + results.Add($"## {record.WorkItem.AssignedTo} - {record.WorkItem.Id} - {record.WorkItem.Title}"); + results.Add(string.Empty); + results.Add($"- [{record.WorkItem.Id}]({url}{record.WorkItem.Id})"); + if (record.Children.Count == 0) + results.Add(string.Empty); + else + { + AppendLines(spaces, results, record, condensed: true, sprintOnly: false); + results.Add(string.Empty); + distinct.Clear(); + AppendLines(spaces, distinct, record, condensed: false, sprintOnly: true); + if (distinct.Count > 1) + { + results.Add($"## Distinct Iteration Path(s) - {record.WorkItem.WorkItemType} - {record.WorkItem.AssignedTo} - {record.WorkItem.Id} - {record.WorkItem.Title} - {record.WorkItem.IterationPath}"); + results.Add(string.Empty); + results.Add($"- [{record.WorkItem.Id}]({url}{record.WorkItem.Id})"); + distinct.Sort(); + distinct = (from l in distinct select l.Trim()).Distinct().ToList(); + results.AddRange(distinct); + results.Add(string.Empty); + maxIterationPath = distinct.Max(); + if (!string.IsNullOrEmpty(maxIterationPath) && maxIterationPath.Contains("] ") && maxIterationPath.Split(']')[1].Trim() != record.WorkItem.IterationPath) + { + results.Add($"### Sync to Distinct Max Iteration Path => {maxIterationPath} - {record.WorkItem.Id} - {record.WorkItem.Title}"); + results.Add(string.Empty); + } + } + results.Add($"## Extended - {record.WorkItem.Id} - {record.WorkItem.Title}"); + results.Add(string.Empty); + AppendLines(spaces, results, record, condensed: false, sprintOnly: false); + results.Add(string.Empty); + } + lines.AddRange(results); + results.Clear(); + } + } + + private static void AppendLines(List spaces, List lines, Record record, bool condensed, bool sprintOnly) + { + string line; + spaces.Add('\t'); + WorkItem workItem; + 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 GetKeyValuePairs(ReadOnlyDictionary keyValuePairs) + { + Dictionary results = new(); + List nests = new(); + WorkItem? parentWorkItem; + ReadOnlyCollection records; + foreach (KeyValuePair keyValuePair in keyValuePairs) + { + nests.Clear(); + if (keyValuePair.Value.Parent is null) + parentWorkItem = null; + else + _ = keyValuePairs.TryGetValue(keyValuePair.Value.Parent.Value, out parentWorkItem); + try + { + records = GetKeyValuePairs(keyValuePairs, keyValuePair.Value, nests); + results.Add(keyValuePair.Key, new(keyValuePair.Value, parentWorkItem, records)); + } + catch (Exception) + { + results.Add(keyValuePair.Key, new(keyValuePair.Value, parentWorkItem, new(Array.Empty()))); + } + } + return new(results); + } + + private static ReadOnlyCollection GetDirectories(string destinationDirectory, ReadOnlyDictionary keyValuePairs) + { + List results = new(); + Record record; + string directory; + List nests = new(); + ReadOnlyCollection childrenDirectories; + string dateDirectory = Path.Combine(destinationDirectory, "_", DateTime.Now.ToString("yyyy-MM-dd")); + foreach (KeyValuePair keyValuePair in keyValuePairs) + { + record = keyValuePair.Value; + if (record.Parent is not null && (record.WorkItem.Parent is null || record.Parent.Id != record.WorkItem.Parent.Value)) + continue; + if (record.Parent is not null) + continue; + // if (record.WorkItem.Id == 110730) + // continue; + // if (record.WorkItem.Id == 110732) + // continue; + nests.Clear(); + directory = Path.Combine(dateDirectory, $"{record.WorkItem.WorkItemType.Substring(0, 1)}-{record.WorkItem.Id}-{record.WorkItem.Title.Trim().Substring(0, 1)}"); + childrenDirectories = GetChildrenDirectories(keyValuePairs, nests, directory, record); + results.AddRange(childrenDirectories); + } + return new(results.Distinct().ToArray()); + } + + private static string GetLine(List spaces, WorkItem workItem, Record record, bool condensed, bool sprintOnly) + { + string result; + string closed = GetClosed(workItem); + result = sprintOnly ? $"\t- [ ] {workItem.IterationPath}" : + condensed ? $"{new string(spaces.Skip(1).ToArray())}- {closed} {record.WorkItem.Id} - {workItem.Title}" : + $"{new string(spaces.Skip(1).ToArray())}- {closed} {record.WorkItem.Id} - {workItem.Title} ~~~ {workItem.AssignedTo} - {workItem.IterationPath.Replace('\\', '-')} - {workItem.CreatedDate} --- {workItem.ClosedDate}"; + return result; + } + + private static ReadOnlyCollection GetKeyValuePairs(ReadOnlyDictionary keyValuePairs, WorkItem workItem, List nests) + { + List results = new(); + int? childId; + nests.Add(true); + WorkItem? childWorkItem; + WorkItem? parentWorkItem; + List collection = new(); + ReadOnlyCollection records; + if (workItem.Relations is not null && workItem.Relations.Length > 0) + { + collection.Clear(); + foreach (Relation relation in workItem.Relations) + { + childId = GetIdFromUrlIfChild(relation); + if (childId is not null && workItem.Parent is not null && relation?.URL is not null && relation.URL.Contains(workItem.Parent.Value.ToString())) + continue; + if (childId is null || !keyValuePairs.TryGetValue(childId.Value, out childWorkItem)) + continue; + collection.Add(childWorkItem); + } + collection = (from l in collection orderby l.State != "Closed", l.Id select l).ToList(); + foreach (WorkItem w in collection) + { + if (nests.Count > 99) + break; + if (w.Parent is null) + parentWorkItem = null; + else + _ = keyValuePairs.TryGetValue(w.Parent.Value, out parentWorkItem); + records = GetKeyValuePairs(keyValuePairs, w, nests); + results.Add(new(w, parentWorkItem, records)); + } + } + return new(results); + } + + private static ReadOnlyCollection GetChildrenDirectories(ReadOnlyDictionary keyValuePairs, List nests, string parentDirectory, Record record) + { + List results = new(); + nests.Add(true); + string directory; + Record? childRecord; + ReadOnlyCollection childrenDirectories; + foreach (Record r in record.Children) + { + // if (record.WorkItem.Id == 110730) + // continue; + // if (record.WorkItem.Id == 110732) + // continue; + directory = Path.Combine(parentDirectory, $"{r.WorkItem.WorkItemType.Substring(0, 1)}-{r.WorkItem.Id}-{r.WorkItem.Title.Trim().Substring(0, 1)}"); + results.Add(directory); + if (!keyValuePairs.TryGetValue(r.WorkItem.Id, out childRecord)) + continue; + if (nests.Count > 99) + break; + childrenDirectories = GetChildrenDirectories(keyValuePairs, nests, directory, childRecord); + results.AddRange(childrenDirectories); + } + return new(results); + } + + private static string GetClosed(WorkItem workItem) => + workItem.State != "Closed" ? "[ ]" : "[x]"; + + private static int? GetIdFromUrlIfChild(Relation relation) + { + int? result; + string[] segments = relation?.Attributes is null || relation.Attributes.Name != "Child" ? Array.Empty() : relation.URL.Split('/'); + if (segments.Length < 2) + result = null; + else + { + if (!int.TryParse(segments[segments.Length - 1], out int id)) + result = null; + else + result = id; + } + return result; + } + + private static void FilterChildren(ReadOnlyCollection workItemTypes, Record record, List results) + { + foreach (Record r in record.Children) + { + if (!workItemTypes.Contains(r.WorkItem.WorkItemType)) + continue; + results.Add(r.WorkItem); + FilterChildren(workItemTypes, r, results); + } + } + + private static ReadOnlyCollection FilterChildren(ReadOnlyCollection workItemTypes, Record record) + { + List 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 string? GetMaxIterationPath122508(ReadOnlyCollection workItems) + { + string? result; + List results = new(); + foreach (WorkItem workItem in workItems) + { + if (results.Contains(workItem.IterationPath)) + continue; + results.Add(workItem.IterationPath); + } + result = results.Count == 0 ? null : results.Max(); + return result; + } + + private static ReadOnlyCollection FeatureCheckIterationPath122508(string url, List lines, ReadOnlyCollection workItemTypes, ReadOnlyCollection records, string workItemType) + { + List results = new(); + string? maxIterationPath; + List collection = new(); + ReadOnlyCollection childrenWorkItems; + foreach (Record record in records) + { + if (record.WorkItem.State is "Removed") + continue; + if (record.WorkItem.WorkItemType != workItemType) + continue; + collection.Clear(); + if (record.Children.Count == 0) + continue; + childrenWorkItems = FilterChildren(workItemTypes, record); + maxIterationPath = GetMaxIterationPath122508(childrenWorkItems); + if (string.IsNullOrEmpty(maxIterationPath) || record.WorkItem.IterationPath == maxIterationPath) + 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}) => {record.WorkItem.IterationPath} != {maxIterationPath}"); + collection.Add(string.Empty); + lines.AddRange(collection); + results.Add(WorkItem.Get(record.WorkItem, $"IterationPath:{record.WorkItem.Id};{record.WorkItem.IterationPath} != {maxIterationPath}")); + } + return new(results); + } + + private static ReadOnlyCollection GetWorkItemsNotMatching122514(Record record, ReadOnlyCollection workItems) + { + List results = new(); + string[] segments; + string[] parentTags = record.WorkItem.Tags.Split(';').Select(l => l.Trim()).ToArray(); + foreach (WorkItem workItem in workItems) + { + segments = string.IsNullOrEmpty(workItem.Tags) ? Array.Empty() : workItem.Tags.Split(';').Select(l => l.Trim()).ToArray(); + if (segments.Length > 0 && parentTags.Any(l => segments.Contains(l))) + continue; + results.Add(workItem); + } + return new(results); + } + + private static ReadOnlyCollection FeatureCheckTag122514(string url, List lines, ReadOnlyCollection workItemTypes, ReadOnlyCollection records, string workItemType) + { + List results = new(); + List collection = new(); + List violations = new(); + ReadOnlyCollection childrenWorkItems; + ReadOnlyCollection workItemsNotMatching; + foreach (Record record in records) + { + if (record.WorkItem.State is "Removed") + continue; + if (record.WorkItem.WorkItemType != workItemType) + continue; + collection.Clear(); + violations.Clear(); + if (record.Children.Count == 0) + continue; + if (string.IsNullOrEmpty(record.WorkItem.Tags)) + workItemsNotMatching = new(new WorkItem[] { record.WorkItem }); + else + { + childrenWorkItems = FilterChildren(workItemTypes, record); + workItemsNotMatching = GetWorkItemsNotMatching122514(record, childrenWorkItems); + if (!string.IsNullOrEmpty(record.WorkItem.Tags) && workItemsNotMatching.Count == 0) + continue; + } + collection.Add($"## {record.WorkItem.AssignedTo} - {record.WorkItem.Id} - {record.WorkItem.Title}"); + collection.Add(string.Empty); + foreach (WorkItem workItem in workItemsNotMatching) + collection.Add($"- [ ] [{workItem}]({url}{workItem}) {nameof(record.WorkItem.Tags)} != {record.WorkItem.Tags}"); + collection.Add(string.Empty); + lines.AddRange(collection); + violations.Add($"Tag:{record.WorkItem.Tags};"); + foreach (WorkItem workItem in workItemsNotMatching) + violations.Add($"{workItem.Id}:{workItem.Tags};"); + results.Add(WorkItem.Get(record.WorkItem, string.Join(" ", violations))); + } + return new(results); + } + + private static ReadOnlyCollection GetWorkItemsNotMatching126169(Record record, ReadOnlyCollection workItems) + { + List results = new(); + foreach (WorkItem workItem in workItems) + { + if (record.WorkItem.Priority is null) + { + results.Add(record.WorkItem); + break; + } + if (workItem.Priority == record.WorkItem.Priority.Value) + continue; + results.Add(workItem); + } + return new(results); + } + + private static ReadOnlyCollection FeatureCheckPriority126169(string url, List lines, ReadOnlyCollection workItemTypes, ReadOnlyCollection records, string workItemType) + { + List results = new(); + List collection = new(); + List violations = new(); + ReadOnlyCollection childrenWorkItems; + ReadOnlyCollection workItemsNotMatching; + foreach (Record record in records) + { + if (record.WorkItem.State is "Removed") + continue; + if (record.WorkItem.WorkItemType != workItemType) + continue; + collection.Clear(); + violations.Clear(); + if (record.Children.Count == 0) + continue; + childrenWorkItems = FilterChildren(workItemTypes, record); + workItemsNotMatching = GetWorkItemsNotMatching126169(record, childrenWorkItems); + if (workItemsNotMatching.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 (WorkItem workItem in workItemsNotMatching) + collection.Add($"- [ ] [{workItem.Id}]({url}{workItem.Id}) {nameof(record.WorkItem.Priority)} != {record.WorkItem.Priority}"); + collection.Add(string.Empty); + lines.AddRange(collection); + violations.Add($"Priority:{record.WorkItem.Priority};"); + foreach (WorkItem workItem in workItemsNotMatching) + violations.Add($"{workItem.Id}:{workItem.Priority};"); + results.Add(WorkItem.Get(record.WorkItem, string.Join(" ", violations))); + } + return new(results); + } + + private static ReadOnlyCollection GetWorkItemsNotMatching123066(Record record, ReadOnlyCollection workItems) + { + List results = new(); + int check; + int state = GetState(record.WorkItem); + List> collection = new(); + foreach (WorkItem workItem in workItems) + { + if (workItem.State is "Removed") + continue; + check = GetState(workItem); + if (check == state) + continue; + collection.Add(new(check, workItem)); + } + if (collection.Count > 0) + { + KeyValuePair[] notNewState = (from l in collection where l.Value.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 keyValuePair in collection.OrderByDescending(l => l.Key)) + results.Add(keyValuePair.Value); + return new(results); + } + + private static ReadOnlyCollection GetWorkItemsNotMatching123067(Record record, ReadOnlyCollection workItems) + { + List results = new(); + int check; + int state = GetState(record.WorkItem); + List> collection = new(); + foreach (WorkItem workItem in workItems) + { + if (workItem.State is "Removed") + continue; + check = GetState(workItem); + if (check == state) + continue; + collection.Add(new(check, workItem)); + } + if (collection.Count > 0) + { + KeyValuePair[] notNewState = (from l in collection where l.Value.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 keyValuePair in collection.OrderByDescending(l => l.Key)) + results.Add(keyValuePair.Value); + return new(results); + } + + private static ReadOnlyCollection FeatureCheckState123066(string url, List lines, ReadOnlyCollection workItemTypes, ReadOnlyCollection records, string workItemType) + { + List results = new(); + List collection = new(); + List violations = new(); + ReadOnlyCollection childrenWorkItems; + ReadOnlyCollection workItemsNotMatching; + foreach (Record record in records) + { + if (record.WorkItem.State is "Removed") + continue; + if (record.WorkItem.WorkItemType != workItemType) + continue; + collection.Clear(); + violations.Clear(); + if (record.Children.Count == 0) + continue; + childrenWorkItems = FilterChildren(workItemTypes, record); + workItemsNotMatching = GetWorkItemsNotMatching123066(record, childrenWorkItems); + if (workItemsNotMatching.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 (WorkItem workItem in workItemsNotMatching) + collection.Add($"- [ ] [{workItem.Id}]({url}{workItem.Id}) {nameof(record.WorkItem.State)} != {record.WorkItem.State}"); + collection.Add(string.Empty); + lines.AddRange(collection); + violations.Add($"State:{record.WorkItem.State};"); + foreach (WorkItem workItem in workItemsNotMatching) + violations.Add($"{workItem.Id}:{workItem.State};"); + results.Add(WorkItem.Get(record.WorkItem, string.Join(" ", violations))); + } + return new(results); + } + + private static ReadOnlyCollection FeatureCheckState123067(string url, List lines, ReadOnlyCollection workItemTypes, ReadOnlyCollection records, string workItemType) + { + List results = new(); + List collection = new(); + List violations = new(); + ReadOnlyCollection childrenWorkItems; + ReadOnlyCollection workItemsNotMatching; + foreach (Record record in records) + { + if (record.WorkItem.State is "Removed") + continue; + if (record.WorkItem.WorkItemType != workItemType) + continue; + collection.Clear(); + violations.Clear(); + if (record.Children.Count == 0) + continue; + childrenWorkItems = FilterChildren(workItemTypes, record); + workItemsNotMatching = GetWorkItemsNotMatching123067(record, childrenWorkItems); + if (workItemsNotMatching.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 (WorkItem workItem in workItemsNotMatching) + collection.Add($"- [ ] [{workItem.Id}]({url}{workItem.Id}) {nameof(record.WorkItem.State)} != {record.WorkItem.State}"); + collection.Add(string.Empty); + lines.AddRange(collection); + violations.Add($"State:{record.WorkItem.State};"); + foreach (WorkItem workItem in workItemsNotMatching) + violations.Add($"{workItem.Id}:{workItem.State};"); + results.Add(WorkItem.Get(record.WorkItem, string.Join(" ", violations))); + } + return new(results); + } + +} \ No newline at end of file diff --git a/Adaptation/FileHandlers/json/FileRead.cs b/Adaptation/FileHandlers/json/FileRead.cs index 6f8add4..3ff6be9 100644 --- a/Adaptation/FileHandlers/json/FileRead.cs +++ b/Adaptation/FileHandlers/json/FileRead.cs @@ -32,7 +32,8 @@ public class FileRead : Shared.FileRead, IFileRead throw new Exception(cellInstanceConnectionName); if (_IsDuplicator) throw new Exception(cellInstanceConnectionName); - NestExistingFiles(_FileConnectorConfiguration); + if (_IsEAFHosted) + NestExistingFiles(_FileConnectorConfiguration); if (!Debugger.IsAttached && fileConnectorConfiguration.PreProcessingMode != FileConnectorConfiguration.PreProcessingModeEnum.Process) _Timer = new Timer(Callback, null, (int)(fileConnectorConfiguration.FileScanningIntervalInSeconds * 1000), Timeout.Infinite); else diff --git a/Adaptation/FileHandlers/json/ProcessData.cs b/Adaptation/FileHandlers/json/ProcessData.cs index 435aa69..11df6d2 100644 --- a/Adaptation/FileHandlers/json/ProcessData.cs +++ b/Adaptation/FileHandlers/json/ProcessData.cs @@ -1,12 +1,9 @@ using Adaptation.Shared; using Adaptation.Shared.Duplicator; using Adaptation.Shared.Methods; -using Microsoft.TeamFoundation.WorkItemTracking.WebApi; using System; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.IO; -using System.Net.Http; using System.Text.Json; namespace Adaptation.FileHandlers.json; @@ -20,19 +17,7 @@ public class ProcessData : IProcessData public ProcessData(IFileRead fileRead, Logistics logistics, - List fileInfoCollection, - HttpClient httpClient, - string basePage, - string api, - string query, - WorkItemTrackingHttpClient workItemTrackingHttpClient, - string project, - ReadOnlyDictionary assignedToNameToEncodedPAT, - ReadOnlyDictionary assignedToNameToUser, - ReadOnlyDictionary requestorNameToUser, - string json, - bool forceUpdatedBy, - bool forceDeleteUpdatedBy) + List fileInfoCollection) { fileInfoCollection.Clear(); _Details = new List(); diff --git a/Adaptation/FileHandlers/json/WorkItems/WorkItem.cs b/Adaptation/FileHandlers/json/WorkItems/WorkItem.cs index 6d93c26..32486e9 100644 --- a/Adaptation/FileHandlers/json/WorkItems/WorkItem.cs +++ b/Adaptation/FileHandlers/json/WorkItems/WorkItem.cs @@ -66,6 +66,8 @@ public class WorkItem WorkItemType = workItemType; } + public override string ToString() => $"{Id} - {WorkItemType} - {Title}"; + public static WorkItem Get(WorkItem workItem, string? violation) { WorkItem result = new(workItem.AreaPath, diff --git a/Adaptation/MESAFIBACKLOG.Tests.csproj b/Adaptation/MESAFIBACKLOG.Tests.csproj index 91c2405..5fc4a37 100644 --- a/Adaptation/MESAFIBACKLOG.Tests.csproj +++ b/Adaptation/MESAFIBACKLOG.Tests.csproj @@ -50,23 +50,23 @@ - + - - - - - + + + + + - - + + NU1701 - - + + - - + + diff --git a/Adaptation/Shared/Test.cs b/Adaptation/Shared/Test.cs index 169f05b..1fdc75c 100644 --- a/Adaptation/Shared/Test.cs +++ b/Adaptation/Shared/Test.cs @@ -3,6 +3,7 @@ namespace Adaptation.Shared; public enum Test { AFMRoughness = 34, + Backlog = 55, //Largest BioRadQS408M = 25, BioRadStratus = 26, BreakdownVoltageCenter = 0, @@ -14,7 +15,7 @@ public enum Test CandelaPSL = 38, CandelaVerify = 37, CDE = 24, - Climatec = 54, //Largest + Climatec = 54, CV = 3, DailyRPMAverage = 19, DailyRPMPLRatio = 20, diff --git a/Adaptation/_Tests/Extract/Production/v2.57.0/MESAFIBACKLOG.cs b/Adaptation/_Tests/Extract/Production/v2.57.0/MESAFIBACKLOG.cs index 56ddc2f..b006bdd 100644 --- a/Adaptation/_Tests/Extract/Production/v2.57.0/MESAFIBACKLOG.cs +++ b/Adaptation/_Tests/Extract/Production/v2.57.0/MESAFIBACKLOG.cs @@ -1,9 +1,11 @@ #if true +using Adaptation.FileHandlers.json.WorkItems; using Adaptation.Shared; using Adaptation.Shared.Methods; using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.Reflection; @@ -66,6 +68,62 @@ public class MESAFIBACKLOG [TestMethod] public void Production__v2_57_0__MESAFIBACKLOG__Markdown() => _MESAFIBACKLOG.Production__v2_57_0__MESAFIBACKLOG__Markdown(); + private static ReadOnlyDictionary GetKeyValuePairs(List collection) + { + Dictionary results = []; + foreach (FileInfo fileInfo in collection) + results.Add(fileInfo.Name, fileInfo); + return new(results); + } + + private static ReadOnlyCollection GetWorkItems(FileInfo fileInfo) + { + WorkItem[] results; + string json = File.ReadAllText(fileInfo.FullName); + results = JsonSerializer.Deserialize(json); + return new(results); + } + + private static void Verify122508(FileInfo fileInfo) + { + ReadOnlyCollection workItems = GetWorkItems(fileInfo); + Assert.IsNotNull(workItems); + // Assert.IsTrue(workItems.Count == 10); + // Assert.IsTrue(workItems.Count == 6); + } + + private static void Verify122514(FileInfo fileInfo) + { + ReadOnlyCollection workItems = GetWorkItems(fileInfo); + Assert.IsNotNull(workItems); + // Assert.IsTrue(workItems.Count == 25); + // Assert.IsTrue(workItems.Count == 6); + } + + private static void Verify126169(FileInfo fileInfo) + { + ReadOnlyCollection workItems = GetWorkItems(fileInfo); + Assert.IsNotNull(workItems); + // Assert.IsTrue(workItems.Count == 1); + // Assert.IsTrue(workItems.Count == 1); + } + + private static void Verify123066(FileInfo fileInfo) + { + ReadOnlyCollection workItems = GetWorkItems(fileInfo); + Assert.IsNotNull(workItems); + // Assert.IsTrue(workItems.Count == 24); + // Assert.IsTrue(workItems.Count == 5); + } + + private static void Verify123067(FileInfo fileInfo) + { + ReadOnlyCollection workItems = GetWorkItems(fileInfo); + Assert.IsNotNull(workItems); + // Assert.IsTrue(workItems.Count == 24); + // Assert.IsTrue(workItems.Count == 5); + } + #if DEBUG [Ignore] #endif @@ -83,6 +141,17 @@ public class MESAFIBACKLOG Assert.IsFalse(string.IsNullOrEmpty(extractResult?.Item1)); Assert.IsNotNull(extractResult.Item3); Assert.IsNotNull(extractResult.Item4); + ReadOnlyDictionary keyValuePairs = GetKeyValuePairs(extractResult.Item4); + Assert.IsTrue(keyValuePairs.ContainsKey("check-122508.json")); + Assert.IsTrue(keyValuePairs.ContainsKey("check-122514.json")); + Assert.IsTrue(keyValuePairs.ContainsKey("check-126169.json")); + Assert.IsTrue(keyValuePairs.ContainsKey("check-123066.json")); + Assert.IsTrue(keyValuePairs.ContainsKey("check-123067.json")); + Verify122508(keyValuePairs["check-122508.json"]); + Verify122514(keyValuePairs["check-122514.json"]); + Verify126169(keyValuePairs["check-126169.json"]); + Verify123066(keyValuePairs["check-123066.json"]); + Verify123067(keyValuePairs["check-123067.json"]); NonThrowTryCatch(); } diff --git a/MESAFIBACKLOG.csproj b/MESAFIBACKLOG.csproj index 7be9ec8..f3eb66a 100644 --- a/MESAFIBACKLOG.csproj +++ b/MESAFIBACKLOG.csproj @@ -138,6 +138,7 @@ +