protected virtual async Task <BarChart> ProjectChart(Summary <JObject, float> summary, Filter <Criterion> filter,
                                                             TimeInterval timeInterval, PropertyValueCategorizer categorizer, 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 <JObject> >();

            foreach (var token in dataArray)
            {
                if (token.Type != JTokenType.Object)
                {
                    throw new JsonArgumentException();
                }
                try{
                    var obj = (JObject)token;
                    var key = categorizer.Categorize(obj);
                    // If the category does not yet exist, add it
                    if (!projectedData.ContainsKey(key))
                    {
                        projectedData.Add(key, new Collection <JObject>());
                    }

                    // Add the value to the category's collection
                    projectedData[key].Add(obj);
                } catch (JsonArgumentException) {}
            }

            // Summarize each category's collection into a summary value,
            // such as a count, 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 <CategorizerCriterion>() // Match data with the same category / key as this bar
                    {
                        Criteria = new List <CategorizerCriterion>()
                        {
                            new CategorizerCriterion(s.Key, categorizer)
                        }
                    },
                    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")
                    })
                }
            }).ToList();

            return(new BarChart()
            {
                Bars = bars,
                Label = "Dataset"
            });
        }
Example #2
0
        protected virtual async Task <GroupedBarChart> ProjectChart(Filter <Criterion> filter, TimeInterval timeInterval,
                                                                    PropertyValueCategorizer superDatasetCategorizer, PropertyValueCategorizer subDatasetCategorizer,
                                                                    Summary <JObject, float> summary, string drilldownAction, string drilldownController)
        {
            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);

            var labeledCollections = new Dictionary <string, IDictionary <string, IEnumerable <JObject> > >();

            // Categorize each token to a super- and sub- dataset,
            // and store in the appropriate collection
            foreach (var token in dataArray)
            {
                if (token.Type != JTokenType.Object)
                {
                    throw new JsonArgumentException();
                }
                try{
                    var obj = (JObject)token;
                    var superDatasetCategory = superDatasetCategorizer.Categorize(obj);
                    var subDatasetCategory   = subDatasetCategorizer.Categorize(obj);
                    // Create dictionary entries if they don't already exist
                    if (!labeledCollections.ContainsKey(superDatasetCategory))
                    {
                        labeledCollections.Add(superDatasetCategory, new Dictionary <string, IEnumerable <JObject> >());
                    }

                    if (!labeledCollections[superDatasetCategory].ContainsKey(subDatasetCategory))
                    {
                        labeledCollections[superDatasetCategory].Add(subDatasetCategory, new Collection <JObject>());
                    }

                    // Add the object to the corresponding collection
                    labeledCollections[superDatasetCategory][subDatasetCategory].Append(obj);
                } catch (JsonArgumentException) {}
            }

            // Summarize each sub-dataset of each dataset into a summary value,
            // such as a mean, median, maximum, etc.
            var summaryValues = new Dictionary <string, IDictionary <string, float> >();

            foreach (var superDataset in labeledCollections)
            {
                summaryValues.Add(superDataset.Key, new Dictionary <string, float>());

                // Summarize each category within the dataset
                foreach (var subDataset in superDataset.Value)
                {
                    // For each sub-dataset in this super-dataset,
                    // construct a summary and store it in the summaryValues
                    summaryValues[superDataset.Key].Add(
                        subDataset.Key,
                        summary.Summarize(subDataset.Value));
                }
            }

            // Construct an ordered list of subLabels for the inner data points.
            // This order must be maintained across all datasets, so this
            // list can be used as the ordering of keys.
            var subLabels = summaryValues.Any() ? summaryValues.First().Value.Select(kvp => kvp.Key).ToList() : new List <string>();

            // Each dataset gets its own color
            int backgroundHue = 0;
            int borderHue     = 0;
            var hueIncrement  = summaryValues.Count() == 0 ? 0 : 360 / summaryValues.Count();

            // Construct a list of bar groups using the summaryValues and the subLabels as a
            // guide for inner key ordering. Note: Select() preserves ordering, so using
            // subLabels.Select() will allow a projection of values preserving
            // the inner ordering.
            var drilldownActions     = subLabels.Select(subLabel => drilldownAction).ToList();
            var drilldownControllers = subLabels.Select(subLabel => drilldownController).ToList();
            var barGroups            = summaryValues.Select(kvp => new BarGroup()
            {
                Label                    = kvp.Key,
                BackgroundColor          = $"hsla({PostIncHue(ref backgroundHue, hueIncrement)}, {BarGroup.BackgroundSaturation}, {BarGroup.BackgroundLightness}, {BarGroup.BackgroundAlpha})",
                BorderColor              = $"hsla({PostIncHue(ref borderHue, hueIncrement)}, {BarGroup.BorderSaturation}, {BarGroup.BorderLightness}, {BarGroup.BorderAlpha})",
                Values                   = subLabels.Select(label => (int)kvp.Value[label]).ToList(),
                DrilldownActions         = drilldownActions,
                DrilldownControllers     = drilldownControllers,
                DrilldownQueryParameters = subLabels.Select(subLabel => (object)new {
                    preFilter = filter,
                    filter    = new Filter <Criterion>(
                        new List <Criterion>()
                    {
                        new CategorizerCriterion(kvp.Key, superDatasetCategorizer),
                        new CategorizerCriterion(subLabel, subDatasetCategorizer)
                    }
                        ), // Drilldown data should match the same super- and sub-datasets (filter)
                    summary,
                    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")
                    })
                }).ToList()
            }).ToList();

            return(new GroupedBarChart()
            {
                BarGroups = barGroups,
                Labels = subLabels
            });
        }
        public virtual async Task <IViewComponentResult> InvokeAsync(Summary <JObject, float> summary, Filter <Criterion> filter,
                                                                     TimeInterval timeInterval, PropertyValueCategorizer categorizer, string drilldownController, string drilldownAction)
        {
            var barChart = await ProjectChart(summary, filter, timeInterval, categorizer, drilldownController, drilldownAction);

            return(await Task.Run(() => View(barChart)));
        }
Example #4
0
        public virtual async Task <IViewComponentResult> InvokeAsync(Summary <JObject, float> summary, Filter <Criterion> filter,
                                                                     TimeInterval timeInterval, PropertyValueCategorizer superDatasetCategorizer, PropertyValueCategorizer subDatasetCategorizer,
                                                                     string drilldownAction, string drilldownController, bool pivot = false)
        {
            var barChart = await ProjectChart(filter, timeInterval, superDatasetCategorizer, subDatasetCategorizer,
                                              summary, drilldownAction, drilldownController);

            return(View(pivot ? barChart.Pivot() : barChart));
        }