In the impact.js framework, what is the structure of level objects produce by the Weltmeister level editor ?
The most information I was able to find on this is the documentation for ig.game.loadlevel, but it is very limited. In particular what is the meaning of the conent of a layer's data property ?
The example from the docs:
{
entities: [
{type: "EntityClassName", x: 64, y: 32, settings: {}},
{type: "EntityClassName", x: 16, y: 0, settings: {}},
],
layer: [
{
name: "background1",
tilesetName: "media/tiles/biolab.png",
repeat: false,
distance: 1,
tilesize: 8,
foreground: false,
data: [
[1,2,6],
[0,3,5],
[2,8,1],
]
},
]
}
The level object has 2 sections, the entities and layers, both of which are arrays. The entities array contains entities that will spawned during level load. In the example above this is equivalent to calling ig.game.spawnEntity(EntityClassName, 64, 32, {})
The objects in the layers array create either an ig.BackgroundMap or an ig.CollsionMap, depending on the name of the map. If the name is "collision", then the game will create a ig.CollisionMap at ig.game.collisionMap. If it's anything else, then it will create an ig.BackgroundMap and add it to the ig.game.backgroundMaps array.
The data property of the layer structure is the tile map itself. The array determines which tile from the tileset to draw.
Related
I am trying to create a line chart using using two separate arrays pulled from a json file to make one one.
Here is what my json file looks like
{
"time": [1240, 1250, 1300, 1310],
"volt": [12.218, 13, 12, 14]
}
Here is the code I thought would work
https://codesandbox.io/s/boring-elbakyan-bj7gg?file=/data.json
which uses
data: {
x: jsonData.time,
y: jsonData.volt,
},
which seemed to make sense to me but isn't working
This works but the time stamps are not displaying current times or doesn't display at all
https://codesandbox.io/s/awesome-hamilton-kkrgt?file=/index.js
Any help is greatly appreciated!!
You need to map your data to the format required by Highcharts. In your case:
an array of arrays with [x, y] values:
series: [{
data: jsonData2.time.map((x, index) => [x, jsonData2.volt[index]])
}]
or an array of objects with { x, y } values:
series: [{
data: jsonData2.time.map((x, index) => ({ x: x, y: jsonData2.volt[index]}))
}]
Live demo: https://codesandbox.io/s/fancy-cloud-mx9z-mx9ze?file=/index.js
API Reference: https://api.highcharts.com/highcharts/series.line.data
I have a bubble chart with multiple datasets. Two points of two different datasets may have the same coordinates (x and y-value) and lay on the same place in the chart. Because the display order of the points is determined according the order of the datasets, the smaller point could be completely covered by the bigger point in front of it.
Is there a option or a way, to display the points in order of their bubble size?
Simplified example of four points. The solution must also work for multiple datasets with each 30+ points.
I am searching a solution to draw the blue point in front of the red point, for the left pair and let the right pair as it is. This order must be independent of the order of the datasets, as it is per point and not per dataset.
Sorting the datasets seems to be no option for me, as the order cannot be determined per dataset, but instead must be determined for every coordinate/point. When drawing a point, it must be checked for this particular coordinate, if any other point with the same coordinates exists and if this point is greater than the current point (if true, the greater point must be drawn before, to not cover up the current point).
const config = {
type: 'bubble',
data: {
datasets: [{
label: 'Dataset 1',
data: [{
x: 1,
y: 1,
r: 20
},
{
x: 2,
y: 1,
r: 15
}
],
borderColor: 'red',
backgroundColor: 'red'
},
{
label: 'Dataset 2',
data: [{
x: 1,
y: 1,
r: 15
},
{
x: 2,
y: 1,
r: 20
}
],
borderColor: 'blue',
backgroundColor: 'blue'
}
]
},
options: {
responsive: true,
scales: {
x: {
suggestedMin: 0,
suggestedMax: 3
}
},
plugins: {
legend: {
position: 'top',
}
}
}
};
var ctx = document.getElementById('chartJSCanvas').getContext('2d');
const chart = new Chart(ctx, config);
<body>
<canvas id="chartJSCanvas" width="300" height="100"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.1.0/chart.js" integrity="sha512-LlFvdZpYhQdASf4aZfSpmyHD6+waYVfJRwfJrBgki7/Uh+TXMLFYcKMRim65+o3lFsfk20vrK9sJDute7BUAUw==" crossorigin="anonymous"></script>
</body>
The easiest way would be to just sort the data in the datasets and then the datasets themselves before drawing them.
An easy way to do this is provided by Array.prototype.forEach and Array.prototype.sort
First sort the data within each dataset like this:
config.data.datasets.forEach(function(element){
element.data.sort(function (a, b) {
return a.r - b.r;
});
});
Then you can sort the data sets by their smallest element like this:
config.data.datasets.sort(function (a, b) {
return a.data[0].r - b.data[0].r;
});
After that, you can regularly pass your config object with ordered datasets to your library call just the way you do it above:
const chart = new Chart(ctx, config);
A mapbox-vector-tile layer is being served from GeoServer (around 500K features points and multiline strings).
I am using mapbox-gl-js to plot the layer at client side and I use expressions to change certain styles(e.g. line color)
I have an external API which will provide me a list of properties for each asset
[{
id: 123,
prop1: 45,
prop2: 78
}, ...]
Now, I want to assign these properties to the corresponding features, so that I will be able to write expressions based on 'prop1' to manipulate the style.
Expression:
[ 'let', 'load_value', ['to-number', ['get', 'prop1']],
[
'case',
[ 'all', ['>=', ['var', 'load_value'], 0], ['<', ['var', 'load_value'], 50] ], 'gray',
[ 'all', ['>=', ['var', 'load_value'], 50], ['<', ['var', 'load_value'], 70] ], 'yellow',
['>=', ['var', 'load_value'], 70], 'red',
'gray'
]
];
I have tried using setFeatureState method and it worked. Problem, the map is terribly slow after doing this. I believe this is because I need to set the feature state for 500K features.
Setting feature state:
data.forEach((datum) => {
this.map.setFeatureState({
source: 'geoserver-source',
sourceLayer: 'mvt-layer',
id: datum.id
}, {
prop1: datum.prop1
});
});
The color changes as per the given conditions. But the map itself becomes very slow after this. Is there any better way of mapping these properties from the client side?
Apparently there is no other way (as of now) using mapbox-gl-js
https://github.com/mapbox/mapbox-gl-js/issues/8753#issuecomment-531284256
I am creating a stacked column chart, and really just testing highcharts out. I would like to hear how people suggest solving the following case:
In a stacked column chart, I would need the following example code:
series: [
{ name:'seed', data: [12, 8, 9]},
{ name:'predicted', data: [121, 88, 97]}
],
xAxis: {
categories: ['tech', 'sport', 'finance']
},
This means that a single object in my db :
{ category: 'tech', seed: 12, predicted: 121 }
Needs to be split into two arrays which could introduce ordering bugs.
Is there no way to pass objects to highcharts and then manipulate them with some options?
Are you wary of depending solely on the order of elements in the data array for determining which category the elements belong to?
If so, I think the xAxis.type option might interest you:
xAxis: {
type: 'category'
},
series: [{
name: 'tech',
data: [{name:"seed", y:12}, {name:"predicted", y:121}]
}, {
name: 'sport',
data: [{name:"seed", y:8}, {name:"predicted", y:88}]
}, {
name: 'finance',
data: [{name:"predicted", y:97}, {name:"seed", y:9}]
}
]
Example: https://jsfiddle.net/ub2gwq61/
From Highcharts API Reference
In a category axis, the point of the chart's series are used for
categories, if not a categories array is defined.
I have a working OOP code that recursively renders a composition of graphical elements to a canvas. There's quite a bit to dislike about it and I'm trying to see what a functional version will look like.
Sure, one can write a specialised recursive pure function, but as the framework involves similar algorithms, I'd like to:
Harness the power of function composition.
See how FP - and its data piping paradigm (transforming data through pure functions) - lands itself to more complex structures than lists (trees/graphs) and less trivial algorithms (than say, finding all odd number by sequentially iterating the list).
Inspired by Lazy.js, I've started coding and got this far:
LazyTree.from( drawing )
.keepNodes( visible )
.keepChildrenOf( nonClipping )
.traverse( log );
But as for map and fold - I have many unanswered questions.
Goal
Here's a simplified version of the problem I'm trying to solve:
Data
A composition (hierarchy) of rectangles. The bounds of each are in relative coordinates (to its parent):
const drawing = {
name: 'Face',
bounds: { x: 10, y: 10, w: 100, h: 100 },
children: [{
name: 'Left eye',
bounds: { x: 10, y: 10, w: 20, h: 20 }, // Abs: (20, 20, 20, 20)
children: [{
name: 'Left pupil',
bounds: { x: 5, y: 5, w: 10, h: 10 } // Abs: (25, 25, 10, 10)
}]
},{
name: 'Right eye',
bounds: { x: 70, y: 10, w: 20, h: 20 }, // Abs: (80, 20, 20, 20)
children: [{
name: 'Right pupil',
bounds: { x: 5, y: 5, w: 10, h: 10 } // Abs: (85, 25, 10, 10)
}]
}]
};
Task - getAbsoluteBounds
The task is to convert this composition to one that has absolute coordinates (as shown in the comments).
Issues and thoughts
Fold?
The absolute coordinates of a child is its relative coordinates transposed by its parent absolute coordinates. So a fold with its accumulator are candidates to do this.
But fold is associated with catamorphism and verbs like combine, and typically returns a single value.
The transformation in question takes a tree and returns an identical structure but with different values - so it sounds more like a map, but one that needs an accumulator.
As far as the accumulator goes, it is worth noting that all the children of a specific node should get the same accumulator. For the data above, both Left eye and Right eye should get the same absolute coordinates of Face (as opposed to the Right eye getting the returned accumulator of Left eye in depth-first-traversal).
Another thing I'm not clear about is who should be in charge of constructing the output tree. Should it be the high-order functions (fold, map, or whatever), or should it be the aggregator?
Stop conditions
Related the the previous section, consider all rectangles to clip their children, and the following composition:
const drawing = {
name: 'Parent',
bounds: { x: 10, y: 10, w: 10, h: 10 },
children: [{
name: 'Child',
bounds: { x: 1000000, y: 1000000, w: 10, h: 10 },
children: [{
name: 'Grandchild',
bounds: { x: 5, y: 5, w: 5, h: 5 }
}]
}]
};
The Child bounds are out-of-bound with relation to its parent (Parent), so branch traversal should stop when traversing to Child (no point traversing to Grandchild).
The question is: How can this be implemented with a fold function? One solution is to stop branch traversal when the accumulator returns an agreed valued (say undefined). But this is somewhat a departure from the fold API for lists.
Pre and post visit
The rendering algorithm involves:
fill( shape );
renderChildren( shape );
stroke( shape );
I wonder how this can be achieved with something like traverse() or each(). Should these take 2 callbacks (pre, post)?
Traversal strategies
Tree traversal may be:
Depth or Breadth first.
Top-down or Bottom-up (for the latter, see a specialised example for transforming an AST, using reduce).
With lists, we have functions like reverse(). Lazy.js allows adding a custom iterator that can then be chained.
So it seems the the FP way to handle traversal strategy is a transforming function. Is there anything else to it?
Summary
I've touched upon a few of the challenges in implementing a rendering algorithm for a tree structure using the data piping model.
I question if any other FP approaches would be more appropriate here? And perhaps the data piping model is not fit for these sort of problems. Or perhaps, I should simply forget the APIs one sees in FP libraries (that deal nearly exclusively lists) and create one that is appropriate for the task at hand (eg, having a map function that also involves an accumulator).
I couldn't find any FP library dedicated for trees, and information out there is typically limited to very simple problems.
So hopefully, someone would reply with something along the lines of 'this is how it should be done'.
As far as I have understood the details you might do as follows.
It will proceed traversing those items remaining within the parent's boundaries, converting their coordinates to absolute and rendering them just afterwards. However if the child's boundaries overlaps the parent's boundaries the child and it's descendants are skipped. No conversion to absolute coordinates and rendering are done for those.
function render(bounds){
console.log("Rendered:", bounds);
}
function relToAbs(o, b = {x: 0, y:0, w:Infinity, h:Infinity}, go = true){
go = o.bounds.x < b.w && o.bounds.y < b.h ? (o.bounds.x += b.x, o.bounds.y += b.y, render(o.bounds), go) : !go;
o.children && go && (o.children = o.children.map(p => relToAbs(p,o.bounds,go)));
return o;
}
var drawing = { name: 'Face',
bounds: { x: 10, y: 10, w: 100, h: 100 },
children: [{ name: 'Left eye',
bounds: { x: 200, y: 10, w: 20, h: 20 }, // Abs: (20, 20, 20, 20)
children: [{ name: 'Left pupil',
bounds: { x: 5, y: 5, w: 10, h: 10 } // Abs: (25, 25, 10, 10)
}]
},
{ name: 'Right eye',
bounds: { x: 70, y: 10, w: 20, h: 20 }, // Abs: (80, 20, 20, 20)
children: [{ name: 'Right pupil',
bounds: { x: 5, y: 5, w: 10, h: 10 } // Abs: (85, 25, 10, 10)
}]
}]
};
console.log(JSON.stringify(relToAbs(drawing),null,2));