protected virtual async Task <BarChart> ProjectChart(Summary <TProjection, float> summary, Filter <Criterion> filter, TimeInterval timeInterval, GroupedProjection <TProjection> projection, string drilldownController, string drilldownAction) { // For each time interval, add a datum to the dataset var rawData = await apiAccess.PullKeyDeviceActivity(timeInterval.Start, timeInterval.End); // Parse string to JObject var rootObject = JObject.Parse(rawData); if (!rootObject.TryGetValue("Data", out var dataArrayToken)) { throw new JsonArgumentException(); } // Convert data array token to JEnumerable and // filter out unwanted data var dataArray = dataArrayToken.AsJEnumerable(); dataArray = filter.FilterData(dataArray); // Project each token to a value, and store // the value in the associated category's // collection var projectedData = new Dictionary <string, Collection <TProjection> >(); foreach (var token in dataArray) { if (token.Type != JTokenType.Object) { throw new JsonArgumentException(); } try{ var kvp = projection.Project((JObject)token); // If the category does not yet exist, add it if (!projectedData.ContainsKey(kvp.Key)) { projectedData.Add(kvp.Key, new Collection <TProjection>()); } // Add the value to the category's collection projectedData[kvp.Key].Add(kvp.Value); } catch (JsonArgumentException) {} } // Summarize each category's collection into a summary value, // such as a mean, median, maximum, etc. var summaryValues = new Dictionary <string, float>(); foreach (var kvp in projectedData) { summaryValues.Add(kvp.Key, summary.Summarize(kvp.Value)); } int backgroundHue = 0; int borderHue = 0; var hueIncrement = 360 / summaryValues.Count(); var orderedSummaryValues = summaryValues.OrderByDescending(s => s.Value).ToList(); var bars = orderedSummaryValues.Select(s => new Bar() { Value = (int)s.Value, Label = s.Key, BackgroundColor = $"hsla({PostIncHue(ref backgroundHue, hueIncrement)}, {Bar.BackgroundSaturation}, {Bar.BackgroundLightness}, {Bar.BackgroundAlpha})", BorderColor = $"hsla({PostIncHue(ref borderHue, hueIncrement)}, {Bar.BorderSaturation}, {Bar.BorderLightness}, {Bar.BorderAlpha})", DrilldownController = drilldownController, DrilldownAction = drilldownAction, DrilldownQueryParameters = new { summary, // Summarize drilldown data in the same way preFilter = filter, filter = new Filter <ProjectionCriterion <string, CategoryProjection <TProjection> > >( new List <ProjectionCriterion <string, CategoryProjection <TProjection> > >() // Match data with the same category / key as this bar { new ProjectionCriterion <string, CategoryProjection <TProjection> >(new CategoryProjection <TProjection>(projection), s.Key) }), timeSeries = new TimeSeries(new List <TimeInterval>() { new TimeInterval(DateTime.ParseExact("2019-06-01", "yyyy-MM-dd", CultureInfo.InvariantCulture), DateTime.ParseExact("2019-06-30", "yyyy-MM-dd", CultureInfo.InvariantCulture), "June"), new TimeInterval(DateTime.ParseExact("2019-07-01", "yyyy-MM-dd", CultureInfo.InvariantCulture), DateTime.ParseExact("2019-07-31", "yyyy-MM-dd", CultureInfo.InvariantCulture), "July"), new TimeInterval(DateTime.ParseExact("2019-08-01", "yyyy-MM-dd", CultureInfo.InvariantCulture), DateTime.ParseExact("2019-08-31", "yyyy-MM-dd", CultureInfo.InvariantCulture), "August"), new TimeInterval(DateTime.ParseExact("2019-09-01", "yyyy-MM-dd", CultureInfo.InvariantCulture), DateTime.ParseExact("2019-09-30", "yyyy-MM-dd", CultureInfo.InvariantCulture), "September") }), // Project drilldown data in the same way, but only project the value, // not the key / value pair (since all keys / categories are the same in a single drilldown chart) projection = new ValueProjection <TProjection>(projection) } }).ToList(); return(new BarChart() { Bars = bars, Label = "Dataset" }); }
public virtual async Task <IViewComponentResult> InvokeAsync(Summary <TProjection, float> summary, Filter <Criterion> filter, TimeInterval timeInterval, GroupedProjection <TProjection> projection, string drilldownController, string drilldownAction) { var barChart = await ProjectChart(summary, filter, timeInterval, projection, drilldownController, drilldownAction); return(await Task.Run(() => View(barChart))); }