Snippets

Piotr Szrajber Smart M.App - Dynamically adjust the computation results by updating the data in the Smart M.App BI

Created by Piotr Szrajber last modified
// 2016-08-08 Piotr Szrajber <piotr.szrajber@hexagongeospatial.com>

// The following snippet of code dynamically updates one of the records of the data used for BI computations - see !!! test !!! part
// This scenario can be applied when it is necessary to manually adjust BI computations, for example in some 2-step algorithm.
// Let's assume that we have data with the following fields:
// id, TYPE, VALUE, WHATEVER
// and that the measure would be computed using and equation, let's say `$sum(floor(VALUE))`
// but another part of the algorithm re-evaluates the computations using `ceil(VALUE)` instead of `floor(VALUE)` for top 10 records.
// 
// We cannot express such a computation in the Expression because it is using context information that cannot be accessed from the expression.
// But we can manually adjust the computations (and later "attach" this adjustment to the "filtered" chart event if necessary)
//
// To do that, let's configure a custom field in the wizard - let's call it `adjust` and assign it a value `0`. Then instead of
// `$sum(floor(VALUE))
// use
// `$sum(floor(VALUE) + adjust)
//
// Notice that in the standard computation the values won't change - `adjust` value is always `0`.
// Here comes the following snippet of code - on demand we can update `adjust` property for certain record (for record with ID=55 in this case)
// and set it to `1`
//
// Then after applying the update and redrawing the "charts", the computation uses floor(VALUE) + 1 for the record with ID=55. And this is what we wanted
// to achieve!

//gsp.ready(function(gsp) { // uncomment to use it in the browser javascript console
    gsp.bi.stage.requireLibraries(function(gvc) {
        gsp.bi.stage.findStage(null, function(stage) {
            var charts = gvc.dc.chartRegistry.list(stage.id());
            var filterDict = {};
            var cf = stage.facts(); // crossfilter instance

            // temporaly suppress current filters
            function suppressFilters() {
                charts.forEach(function(chart) {
                    filterDict[chart.id()] = chart.filters();
                    chart.filterAll();
                });
            }

            // resume previously suppressed filters
            function resumeFilters() {
                charts.forEach(function(chart) {
                    if (filterDict[chart.id()]) {
                        filterDict[chart.id()].map(chart.filter);
                        delete filterDict[chart.id()];
                    }
                });
            }

            // function for filtering unique records by ID
            function filterById(record) {
                return record.id;
            }

            // dimension on unique IDs
            var idDim = cf.dimension(filterById);

            // function for dynamically modifying record's value, for example after some computations
            function update_record(id, changes) {
                suppressFilters();
                idDim.filter(id);
                var record = idDim.top(Infinity)[0];
                cf.remove();
                for (var keyName in changes) {
                    record[keyName] = changes[keyName];
                }
                cf.add([record]);
                idDim.filterAll();
                resumeFilters();
            }

            // !!! begin test !!!
            update_record("55", {
                adjust: 1
            });
            charts.map(function(ch) {
                ch.redraw()
            })
            // !!! end test !!!

        });
    });
//}); // uncomment to use it in the browser javascript console

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.