Mapbox js - tileset colors assignment - mapbox-gl-js

I am trying to create a colored uk areas map - I need the colors to be driven by local data (say for example sales by postcode), which will always change depending on user selections like report date ranges etc. I have a tileset source which I am assigning to a layer, as in the following (sensitive values blanked out):
this.map.addLayer({
"id": "uk-pc-data",
"type": "fill",
"source-layer": "***",
"source": {
type: 'vector',
url: '***'
}
});
I am then able to style the postcode areas within the tileset by addressing a name property on the tileset features, like so:
"paint": {
"fill-color": [
"match",
["get", "name", [{name: "PR"}, {name: "CH"}, {name: "LN"}]],
[
"PR",
"DD",
"AL",
"PO"
],
"hsla(344, 84%, 29%, 0.37)",
"hsla(131, 94%, 34%, 0)"
]
}
The above will assign one color to the matched areas, and a default to all the other (the non matched ones); What I would like to do, is computing the colour value locally (so based on data constantly changing) based on the feature name, like so
"paint": {
"fill-color": function (feature = {}) {
return localSalesByArea(feature.name)
}
}
This though does not seem to be possible: any help or pointers appreciated; I have been through examples from Mapbox
such as choroplet, heatmaps, expressions but these seem to rely on values delivered via the dataset itself (i.e Population), in my case the values which determine the color scale are separated (they come from an internal reporting api)

If the data on which the colours are determined does not exist in the tileset, you basically have to do a gigantic lookup by name.
You will have a function that generates the fill-color expression, something like:
function makeFillExpression(valuesByName) {
function valueToColor(value) {
return /* insert your choroplething special sauce here */;
}
return ret = [
"match",
["get", "name"],
Object.keys(valuesByName).map(name => valueToColor(valuesByName[name])),
'black'
];
}
Yes, it will be a very large and unwieldy expression.

Related

MUI Data Grid Pro export state not working properly

I am using MUI's Data Grid Pro's new api.exportState() function. In the provided example available here, it is possible to hide a column and have this reflected in the output of the exportState function (the 'columnVisibilityModel' field of the JSON):
{
"columns": {
"columnVisibilityModel": {
"id": false,
"commodity": false
}
....
}
}
However, when running locally, the output of the export state function does not include this field. All other fields such as dimensions, filter, sorting etc. are present. Both my local version and the one in the example are v.12.0

Create Entities and training phrases for values in functions for google action

I have created a trivia game using the SDK, it takes user input and then compares it to a value in my DB to see if its correct.
At the moment, I am just passing a raw input variable through my conversation, this means that it regularly fails when it mishears the user since the exact string which was picked up is rarely == to the value in the DB.
Specifically I would like it to only pick up numbers, and for example realise that it must extract '10' , from a speech input of 'my answer is 10'.
{
"actions": [
{
"description": "Default Welcome Intent",
"name": "MAIN",
"fulfillment": {
"conversationName": "welcome"
},
"intent": {
"name": "actions.intent.MAIN"
}
},
{
"description": "response",
"name": "Raw input",
"fulfillment": {
"conversationName": "rawInput"
},
"intent": {
"name": "raw.input",
"parameters": [{
"name": "number",
"type": "org.schema.type.Number"
}],
"trigger": {
"queryPatterns":[
"$org.schema.type.Number:number is the answer",
"$org.schema.type.Number:number",
"My answer is $org.schema.type.Number:number"
]
}
}
}
],
"conversations": {
"welcome": {
"name": "welcome",
"url": "https://us-central1-triviagame",
"fulfillmentApiVersion": 2
},
"rawInput": {
"name": "rawInput",
"url": "https://us-central1-triviagame",
"fulfillmentApiVersion": 2
}
}
}
app.intent('actions.intent.MAIN', (conv) => {
conv.data.answers = answersArr;
conv.data.questions = questionsArr;
conv.data.counter = answersArr.length;
var thisQuestion = conv.data.questions;
conv.ask((conv.data.answers)[0]));
});
app.intent('raw.input', (conv, input) => {
if(input == ((conv.data.answers)[0])){
conv.ask(nextQuestion());
}
app.intent('actions.intent.TEXT', (conv,input) => {
//verifying if input and db value are equal
// at the moment input is equal to 'my number is 10' (for example) instead of '10'
//therefore the string verification never works
conv.ask(nextQuestion());
});
In a previous project i used the dialogflow UI and I used this #system.entities number parameter along with creating some training phrases so it understands different speech patterns.
This input parameter I am passing through my conv , is only a raw string where I'd like it to be filtered using some sort of entity schema.
How do I create the same effect of training phrases/entities using the JSON file?
You can't do this using just the Action SDK. You need a Natural Language Processing system (such as Dialogflow) to handle this as well. The Action SDK, by itself, will do speech-to-text, and will use the actions.json configuration to help shape how to interpret the text. But it will only return the entire text from the user - it will not try to determine how it might match an Intent, nor what parameters may exist in it.
To do that, you need an NLP/NLU system. You don't need to use Dialogflow, but you will need something that does the parsing. Trying to do it with simple pattern matching or regular expressions will lead to nightmares - find a good system to do it.
If you want to stick to things you can edit yourself, Dialogflow does allow you to download its configuration files (they're just JSON), edit them, and update or replace the configuration through the UI or an API.

Rally SDK 2.0: How to display multiple data columns with a TimeSeriesCalculator

I would like to display 2 time series of data with columns in the same "Rally.ui.chart.Chart". The config below for "Rally.data.lookback.calculator.TimeSeriesCalculator" stacks the columns on the same X column. Is there an easy way to group the data to be shown side-by-side instead for the same date (like the "accepted" and "time remaining" in the iteration burn-down chart) ?
Perhaps something like this?
getMetrics: function () {
return [
{
"field": "TaskRemainingTotal",
"as": "Hours Remaining",
"f": "sum",
"display": "column"
},
{
"field": "PlanEstimate",
"as": "Story Points Accepted",
"f": "filteredSum",
"filterField": "ScheduleState",
"filterValues": ["Accepted", "Verified"],
"display": "column",
"group": "1" //????? is there a specifier to separate this data?
},
];
},
Here is the code for the calculator used for the burn chart:
https://github.com/RallyApps/app-catalog/blob/master/src/apps/charts/burndown/BurnDownCalculator.js
Writing calculators for generating charts from lookback api is probably the most difficult thing to do in the app platform, so kudos for tackling it!
I'm not an expert either, but hopefully that above code is enough to point you in the right direction. Please post back if you either solve it or run into a new issue.
I was able to get it to work by adding the following to the chartConfig:
plotOptions: {
column: {
stacking: null
}
}
I've found some more on this subject that I believe may be helpful:
The "stack" member of the series config in highcharts allows a series to be stacked by name. We can create a much more flexible system that allow us to specify how to stack the data by using this and overriding some methods in the Rally.data.lookback.calculator.TimeSeriesCalculator to allow the series data to be modified.
prepareChartData returns series data, so we can override the output of that to add series data:
prepareChartData: function(store) {
var snapshots = [];
store.each(function(record) {
snapshots.push(record.raw);
});
var a = this.runCalculation(snapshots);
for (var k in a.series) {
if (a.series[k].name.startsWith("Story")) a.series[k].stack = "Story";
}
return a;
}
we can override the _buildSeriesConfig function to push any properties listed in the seriesConfig array in the metric config to the series config. This allows us to specify the series formatting in a nicer way and also gives us much more power in modifying other attributes of the chart config :
_buildSeriesConfig: function(calculatorConfig) {
var aggregationConfig = [],
metrics = calculatorConfig.metrics,
derivedFieldsAfterSummary = calculatorConfig.deriveFieldsAfterSummary;
for (var i = 0, ilength = metrics.length; i < ilength; i += 1) {
var metric = metrics[i];
var seriesConfig = {
name: metric.as || metric.field,
type: metric.display,
dashStyle: metric.dashStyle || "Solid"
};
for (var k in metric.seriesConfig) {
seriesConfig[k] = metric.seriesConfig[k];
}
aggregationConfig.push(seriesConfig);
}
for (var j = 0, jlength = derivedFieldsAfterSummary.length; j < jlength; j += 1) {
var derivedField = derivedFieldsAfterSummary[j];
var seriesConfig = {
name: derivedField.as,
type: derivedField.display,
dashStyle: derivedField.dashStyle || "Solid"
};
for (var k in derivedField.seriesConfig) {
seriesConfig[k] = derivedField.seriesConfig[k];
}
aggregationConfig.push(seriesConfig);
}
return aggregationConfig;
},
this method allows us to supply a seriesConfig property in getMetrics like so:
getMetrics: function() {
return [{
"field": "TaskRemainingTotal", // the field in the data to operate on
"as": "Hours Remaining", // the label to appear on the chart
"f": "sum", // summing function to use.
"display": "column", // how to display the point on the chart.
seriesConfig: {
"stack": "Hours",
"color": "#005eb8"
}
}, {
"field": "PlanEstimate", // the field in the data to operate on
"as": "Story Points Accepted", // the label to appear on the chart
"f": "filteredSum",
"filterField": "ScheduleState", // Only use points in seduled sate accepted or Verified
"filterValues": ["Accepted", "Verified"],
"display": "column",
seriesConfig: {
"stack": "Points",
"color": "#8dc63f"
}
}, {
"field": "PlanEstimate", // the field in the data to operate on
"as": "Story Points Remaining", // the label to appear on the chart
"f": "filteredSum",
"filterField": "ScheduleState", // Only use points in seduled sate accepted or Verified
"filterValues": ["Idea", "Defined", "In Progress", "Completed"],
"display": "column",
seriesConfig: {
"stack": "Points",
"color": "#c0c0c0"
}
},
];
},
With option #2, we can control and add any series config data in the same context that we are configuring the metrics, without worrying about configuration orders. Option #2 is a little dangerous though as the underscore implies that the method is private and therefore has no contractual guarantee to remain compatible in future revisions. (Maybe the rally guys will see this and extend the functionality for us)

RESTful master/detail

Having 3 dropdown pickers in a web application. The web application uses a Restful service to populate pickers data.
The two first pickers get their values from something like /years and /colors. The third one should get its values depending on the settings of the two.
So it could be something like /models?year=1&color=red.
The question is, how to make this HATEOAS-compliant (so that the dev does not have to know the way he should create an url to get the models).
The root / gets me a number of links, such as:
{
"_links": {
"colors": "/colors",
"years": "/years",
"models": "???" }
}
What should be instead of ???? If there was some kind of template /models?color={color}&year={year}, the dev would have to create the url. Is this OK?
Or there could be a link to list of years on each color got from /colors and then a link to list of models on each year got from /years?color=red, but i'd have to first choose color, then populate years and then populate models. Any idea if i want to have the model dependent on both color and year, not just the year populated from color?
Is it even possible in this situation to make it hateoas-compliant?
I have not heard of HATEOAS before, but based on what I just read about it, it seems that it supposed to return links to where the consumer of the service can go forward in the "state machine".
In your case that would translate to the links being "function calls". The first two (/colors and /years) are functions that take no parameters (and return "something" at this point), while the third is a function call that takes two parameters: one that is a representation of a color, the other a year. For the first two having a simple URL will suffice for the link, but for the third, you need to include the parameter name/type information as well. Something like:
{
"_links": {
"colors": "/colors",
"years": "/years",
"models": {
"url": "/models",
"param1": {"color"}
"param2": {"year"}
}
}
}
Note: you can use the same layout as "models" for "colors" and "years" as well.
At this point the client knows what the URL to access the functions are and what the parameter (if any) names are to be passed to the function.
One more thing is missing: types. Although you could just use "string", it will not be obvious that the "color" parameter is actually a value from what "/colors" returns. You can be introducing a "type" Color that describes a color (and any functions that operate on a color: give a displayable name, HTML color code, etc.)
The "beefed up" signature becomes:
{
"_links": {
"colors": {
"url": "/colors",
"return": "/type/List?type=/type/Color"
},
"years": {
"url": "/years",
"return": "/type/List?type=/type/Integer"
},
"models": {
"url": "/models",
"param1": {
"name": "color",
"type": "/type/Color"
},
"param2": {
"name": "year",
"type": "/type/Integer"
}
"return": "/type/List?type=/type/Model"
}
}
}
Note: the path "/type" is used just to separate the types from functions, but is not necessary.
This will interchangeably and discoverably describe the functions, what parameters they take, and what values they are returning, so you can use the right value at the right place.
Of course implementing this on the service end will not be easy (especially with parameterized types, like "/type/List" -- think Generics in Java or templates in C++), but this is the most "safe" and "portable" way you can describe your interface to your clients.

Select an item from Dojo Grid's store and display one of its attributes (array of objects) on grid

I have a Dojo EnhancedGrid which uses a data store filled with the following data structure:
[
{ id: 1, desc: "Obj Desc", options: [ { txt: "text", value: 0 }, { obj2 }, { objn } ] },
{ id: 2, ... },
{ id: 3, ... },
{ id: n, ... }
]
Currently I'm doing all this with an auxiliary store...but I believe this is far from a good approach to the problem, it's too ugly and doesn't work really well with edition (because I have to send changes from one store to another).
Instead of displaying all this objects at the same time, I wanted to select just one object (using its id) and display its options objects on grid. At the same time, the changes on grid should make effect on store, to be able to save them later.
Is it possible to query the grid's store, in order to display just one object? How?
And is it possible to fill the grid with objects list present on "options" attribute?