/// <summary> /// Calculates the average grade of all the linked key results. /// </summary> /// <param name="objective">The objective to score</param> /// <returns>AverageResult without the objective</returns> private static async Task <AverageResult> CalculateAverage(WorkItem objective) { // Request all the work items at the same time. IEnumerable <Task <KeyResult> > asyncOps = objective.Relations .Where(r => r.Rel == "System.LinkTypes.Hierarchy-Forward") .Select(r => GetWorkItemAsync <KeyResult>($"{r.Url}?$Expand=relations")); var workitems = await Task.WhenAll(asyncOps); int items = 0; double total = 0; foreach (var workitem in workitems) { // They may link items to the objective like tasks or user stories. // This makes sure we only count the key results. if (workitem.WorkItemType == KeyResult.WorkItemTypeValue) { items++; total += workitem.Grade; } } // Build and return a dynamic type var result = new AverageResult { Items = items, Total = total, Average = total / items }; return(result); }
/// <summary> /// Uses the hook to request the objective work item and find all the /// linked key results to average. /// </summary> /// <param name="hook"></param> /// <returns>AverageResult with the objective</returns> public static async Task <AverageResult> ProcessObjective(Hook hook) { var objectiveRef = hook.Resource.Revision.Relations.First(r => r.Rel == "System.LinkTypes.Hierarchy-Reverse"); var requestUri = $"{objectiveRef.Url}?$Expand=relations"; var objective = await GetWorkItemAsync <WorkItem>(requestUri); var average = await CalculateAverage(objective); // Build and return a dynamic type var result = new AverageResult { Objective = objective, Items = average.Items, Total = average.Total, Average = average.Average }; return(result); }