From 41933b98d2949dc3097c4cd9717e5e5c3fd84cba Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Fri, 4 Oct 2024 18:10:14 -0700 Subject: [PATCH] FeatureCheckTag --- Adaptation/FileHandlers/json/FileRead.cs | 253 +++++++++++++++++++---- 1 file changed, 214 insertions(+), 39 deletions(-) diff --git a/Adaptation/FileHandlers/json/FileRead.cs b/Adaptation/FileHandlers/json/FileRead.cs index 48e82e7..b0df351 100644 --- a/Adaptation/FileHandlers/json/FileRead.cs +++ b/Adaptation/FileHandlers/json/FileRead.cs @@ -18,6 +18,7 @@ namespace Adaptation.FileHandlers.json; public class FileRead : Shared.FileRead, IFileRead { + private readonly string _URL; private readonly Timer _Timer; private readonly ReadOnlyCollection _WorkItemTypes; @@ -34,6 +35,7 @@ public class FileRead : Shared.FileRead, IFileRead 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('|')); NestExistingFiles(_FileConnectorConfiguration); @@ -290,8 +292,9 @@ public class FileRead : Shared.FileRead, IFileRead spaces.RemoveAt(0); } - private static void AppendLines(List spaces, List lines, ReadOnlyDictionary workItemAndChildren, string workItemType) + private static void AppendLines(string url, List spaces, List lines, ReadOnlyDictionary workItemAndChildren, string workItemType) { + List results = new(); WorkItem workItem; string? maxIterationPath; List distinct = new(); @@ -302,53 +305,210 @@ public class FileRead : Shared.FileRead, IFileRead // continue; if (workItem.WorkItemType != workItemType) continue; - lines.Add($"## {workItem.AssignedTo} - {workItem.Id} - {workItem.Title}"); - lines.Add(string.Empty); - lines.Add($"- [{workItem.Id}](https://tfs.intra.infineon.com/tfs/FactoryIntegration/ART%20SPS/_workitems/edit/{workItem.Id})"); + results.Add($"## {workItem.AssignedTo} - {workItem.Id} - {workItem.Title}"); + results.Add(string.Empty); + results.Add($"- [{workItem.Id}]({url}{workItem.Id})"); if (keyValuePair.Value.Children.Count == 0) - lines.Add(string.Empty); + results.Add(string.Empty); else { - AppendLines(spaces, lines, keyValuePair.Value, condensed: true, sprintOnly: false); - lines.Add(string.Empty); + AppendLines(spaces, results, keyValuePair.Value, condensed: true, sprintOnly: false); + results.Add(string.Empty); distinct.Clear(); AppendLines(spaces, distinct, keyValuePair.Value, condensed: false, sprintOnly: true); if (distinct.Count > 1) { - lines.Add($"## Distinct Iteration Path(s) - {workItem.WorkItemType} - {workItem.AssignedTo} - {workItem.Id} - {workItem.Title} - {workItem.IterationPath}"); - lines.Add(string.Empty); - lines.Add($"- [{workItem.Id}](https://tfs.intra.infineon.com/tfs/FactoryIntegration/ART%20SPS/_workitems/edit/{workItem.Id})"); + 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(); - lines.AddRange(distinct); - lines.Add(string.Empty); + results.AddRange(distinct); + results.Add(string.Empty); maxIterationPath = distinct.Max(); if (!string.IsNullOrEmpty(maxIterationPath) && maxIterationPath.Contains("] ") && maxIterationPath.Split(']')[1].Trim() != workItem.IterationPath) { - lines.Add($"### Sync to Distinct Max Iteration Path => {maxIterationPath} - {workItem.Id} - {workItem.Title}"); - lines.Add(string.Empty); + results.Add($"### Sync to Distinct Max Iteration Path => {maxIterationPath} - {workItem.Id} - {workItem.Title}"); + results.Add(string.Empty); } } - lines.Add($"## Extended - {workItem.Id} - {workItem.Title}"); - lines.Add(string.Empty); - AppendLines(spaces, lines, keyValuePair.Value, condensed: false, sprintOnly: false); - lines.Add(string.Empty); + results.Add($"## Extended - {workItem.Id} - {workItem.Title}"); + results.Add(string.Empty); + AppendLines(spaces, results, keyValuePair.Value, condensed: false, sprintOnly: false); + results.Add(string.Empty); } + lines.AddRange(results); + results.Clear(); } } - private static void WriteMarkdownFile(FileConnectorConfiguration fileConnectorConfiguration, string[] alternateTargetFolders, ReadOnlyCollection workItems, ReadOnlyCollection workItemTypes) + private static void WriteFiles(string destinationDirectory, string fileName, ReadOnlyCollection lines) + { + 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); + string htmlFile = Path.Combine(destinationDirectory, $"{fileName}.html"); + string htmlOld = !File.Exists(htmlFile) ? string.Empty : File.ReadAllText(htmlFile); + if (html != htmlOld) + File.WriteAllText(htmlFile, html); + } + + private static ReadOnlyCollection FilterChildren(Record record, ReadOnlyCollection workItemTypes) + { + List results = new(); + WorkItem workItem; + foreach (KeyValuePair keyValuePair in record.Children) + { + workItem = keyValuePair.Value.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 void FeatureCheckIterationPath(string url, List lines, ReadOnlyCollection workItemTypes, ReadOnlyDictionary workItemAndChildren, string workItemType) + { + WorkItem workItem; + string? maxIterationPath; + List results = new(); + ReadOnlyCollection workItems; + foreach (KeyValuePair keyValuePair in workItemAndChildren) + { + workItem = keyValuePair.Value.WorkItem; + if (workItem.WorkItemType != workItemType) + continue; + results.Clear(); + if (keyValuePair.Value.Children.Count == 0) + continue; + workItems = FilterChildren(keyValuePair.Value, workItemTypes); + maxIterationPath = GetMaxIterationPath(workItems); + if (string.IsNullOrEmpty(maxIterationPath) || workItem.IterationPath == maxIterationPath) + continue; + results.Add($"## {workItem.AssignedTo} - {workItem.Id} - {workItem.Title}"); + results.Add(string.Empty); + results.Add($"- [{workItem.Id}]({url}{workItem.Id})"); + results.Add($"- [ ] {workItem.Id} => {workItem.IterationPath} != {maxIterationPath}"); + results.Add(string.Empty); + lines.AddRange(results); + } + } + + private static ReadOnlyCollection GetIdsNotMatching(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.Id); + } + return new(results); + } + + private static void FeatureCheckTag(string url, List lines, ReadOnlyCollection workItemTypes, ReadOnlyDictionary workItemAndChildren, string workItemType) + { + WorkItem workItem; + List results = new(); + ReadOnlyCollection idsNotMatching; + ReadOnlyCollection workItems; + foreach (KeyValuePair keyValuePair in workItemAndChildren) + { + workItem = keyValuePair.Value.WorkItem; + if (workItem.WorkItemType != workItemType) + continue; + results.Clear(); + if (keyValuePair.Value.Children.Count == 0) + continue; + if (string.IsNullOrEmpty(workItem.Tags)) + idsNotMatching = new(new int[] { workItem.Id }); + else + { + workItems = FilterChildren(keyValuePair.Value, workItemTypes); + idsNotMatching = GetIdsNotMatching(workItem.Tags, workItems); + if (!string.IsNullOrEmpty(workItem.Tags) && idsNotMatching.Count == 0) + continue; + } + results.Add($"## {workItem.AssignedTo} - {workItem.Id} - {workItem.Title}"); + results.Add(string.Empty); + results.Add($"- [{workItem.Id}]({url}{workItem.Id})"); + foreach (int id in idsNotMatching) + results.Add($"- [ ] {id} {nameof(workItem.Tags)} != {workItem.Tags}"); + results.Add(string.Empty); + lines.AddRange(results); + } + } + + private static ReadOnlyCollection GetIdsNotMatching(int? priority, ReadOnlyCollection workItems) + { + List results = new(); + foreach (WorkItem workItem in workItems) + { + if (workItem.Priority == priority) + continue; + results.Add(workItem.Id); + } + return new(results); + } + + private static void FeatureCheckPriority(string url, List lines, ReadOnlyCollection workItemTypes, ReadOnlyDictionary workItemAndChildren, string workItemType) + { + WorkItem workItem; + List results = new(); + ReadOnlyCollection idsNotMatching; + ReadOnlyCollection workItems; + foreach (KeyValuePair keyValuePair in workItemAndChildren) + { + workItem = keyValuePair.Value.WorkItem; + if (workItem.WorkItemType != workItemType) + continue; + results.Clear(); + if (keyValuePair.Value.Children.Count == 0) + continue; + workItems = FilterChildren(keyValuePair.Value, workItemTypes); + idsNotMatching = GetIdsNotMatching(workItem.Priority, workItems); + if (idsNotMatching.Count == 0) + continue; + results.Add($"## {workItem.AssignedTo} - {workItem.Id} - {workItem.Title}"); + results.Add(string.Empty); + results.Add($"- [{workItem.Id}]({url}{workItem.Id})"); + foreach (int id in idsNotMatching) + results.Add($"- [ ] {id} {nameof(workItem.Priority)} != {workItem.Priority}"); + results.Add(string.Empty); + lines.AddRange(results); + } + } + + private static void WriteMarkdownFile(FileConnectorConfiguration fileConnectorConfiguration, string url, string[] alternateTargetFolders, ReadOnlyCollection workItems, ReadOnlyCollection workItemTypes) { - string old; - string html; - string text; string json; - string checkFile; string? pathRoot; List spaces = new(); List lines = new(); ReadOnlyDictionary keyValuePairs = GetWorkItems(workItems); + ReadOnlyCollection userStoryWorkItemTypes = new(new string[] { "User Story" }); ReadOnlyDictionary workItemAndChildren = GetWorkItemAndChildren(keyValuePairs); + ReadOnlyCollection userStoryTaskWorkItemTypes = new(new string[] { "User Story", "Task" }); foreach (string alternateTargetFolder in alternateTargetFolders) { if (alternateTargetFolder == fileConnectorConfiguration.TargetFileLocation) @@ -375,22 +535,37 @@ public class FileRead : Shared.FileRead, IFileRead lines.Clear(); lines.Add("# WorkItems"); lines.Add(string.Empty); - AppendLines(spaces, lines, workItemAndChildren, workItemType); - checkFile = Path.Combine(alternateTargetFolder, $"{workItemType}.md"); - text = string.Join(Environment.NewLine, lines); - old = !File.Exists(checkFile) ? string.Empty : File.ReadAllText(checkFile); - if (text != old) - File.WriteAllText(checkFile, text); - checkFile = Path.Combine(alternateTargetFolder, $"{workItemType}.html"); - html = CommonMark.CommonMarkConverter.Convert(text); - old = !File.Exists(checkFile) ? string.Empty : File.ReadAllText(checkFile); - if (html != old) - File.WriteAllText(checkFile, html); + AppendLines(url, spaces, lines, workItemAndChildren, workItemType); + WriteFiles(alternateTargetFolder, workItemType, new(lines)); + } + { + lines.Clear(); + string workItemType = "Feature"; + lines.Add($"# {nameof(FeatureCheckIterationPath)}"); + lines.Add(string.Empty); + FeatureCheckIterationPath(url, lines, userStoryTaskWorkItemTypes, workItemAndChildren, workItemType); + WriteFiles(alternateTargetFolder, $"{nameof(FeatureCheckIterationPath)}", new(lines)); + } + { + lines.Clear(); + string workItemType = "Feature"; + lines.Add($"# {nameof(FeatureCheckTag)}"); + lines.Add(string.Empty); + FeatureCheckTag(url, lines, userStoryWorkItemTypes, workItemAndChildren, workItemType); + WriteFiles(alternateTargetFolder, $"{nameof(FeatureCheckTag)}", new(lines)); + } + { + lines.Clear(); + string workItemType = "Feature"; + lines.Add($"# {nameof(FeatureCheckPriority)}"); + lines.Add(string.Empty); + FeatureCheckPriority(url, lines, userStoryWorkItemTypes, workItemAndChildren, workItemType); + WriteFiles(alternateTargetFolder, $"{nameof(FeatureCheckPriority)}", new(lines)); } } } - private static void ParseWorkItemsAsync(FileConnectorConfiguration fileConnectorConfiguration, string[] alternateTargetFolders, ReadOnlyCollection workItemTypes) + private static void ParseWorkItemsAsync(FileConnectorConfiguration fileConnectorConfiguration, string url, string[] alternateTargetFolders, ReadOnlyCollection workItemTypes) { if (!Directory.Exists(fileConnectorConfiguration.TargetFileLocation)) _ = Directory.CreateDirectory(fileConnectorConfiguration.TargetFileLocation); @@ -400,15 +575,15 @@ public class FileRead : Shared.FileRead, IFileRead if (workItems.Count > 0) { ParseWorkItemsAsync(fileConnectorConfiguration, alternateTargetFolders, workItems); - WriteMarkdownFile(fileConnectorConfiguration, alternateTargetFolders, workItems, workItemTypes); + WriteMarkdownFile(fileConnectorConfiguration, url, alternateTargetFolders, workItems, workItemTypes); } } - private static void ParseWorkItemsAsync(FileConnectorConfiguration fileConnectorConfiguration, ReadOnlyCollection workItemTypes) + private static void ParseWorkItemsAsync(FileConnectorConfiguration fileConnectorConfiguration, string url, ReadOnlyCollection workItemTypes) { string[] alternateTargetFolders = fileConnectorConfiguration.AlternateTargetFolder.Split('|'); if (alternateTargetFolders.Length > 0) - ParseWorkItemsAsync(fileConnectorConfiguration, alternateTargetFolders, workItemTypes); + ParseWorkItemsAsync(fileConnectorConfiguration, url, alternateTargetFolders, workItemTypes); } private void Callback(object state) @@ -416,7 +591,7 @@ public class FileRead : Shared.FileRead, IFileRead try { if (_IsEAFHosted) - ParseWorkItemsAsync(_FileConnectorConfiguration, _WorkItemTypes); + ParseWorkItemsAsync(_FileConnectorConfiguration, _URL, _WorkItemTypes); } catch (Exception exception) {