Modify multiple array elements simultaneously javascript - javascript

I'm making a simple rogue like game in JavaScript. I can generate a map procedurally without any issue, however I'm looking for a more ergonomic way of manually populating a map array. Here's an example of what I'm talking about.
This works.
//creating empty map array
city = new Array(1500);
//creating tile formats
tile1 = {walk: true, ...etc};
tile2 = {walk: false, ...etc};
//manually modifying array.
city[0] = tile1;
city[1] = tile1;
city[2] = tile1;
However, since some of these maps will be rather large, I'd like to be able to modify multiple elements all at once. The following doesn't work, but expresses what I'd like to do.
city[0,1,2,3,7,8,9,10] = tile1;
city[4,5,6,11,12,13] = tile2;
I tried quite a few different methods, but wasn't successful with any of them. I can't use a for statement without using math more complicated than it'd be worth since I'm using a single array to represent 2d space, and the tiles are not sequential.
Any suggestions?

Use forEach with ES6 arrow function in latest browsers
//creating empty map array
city = new Array(1500);
//creating tile formats
tile1 = {
walk: true
};
tile2 = {
walk: false
};
[0, 1, 2, 3, 7, 8, 9, 10].forEach(v => city[v] = tile1);
// older browser use [0, 1, 2, 3, 7, 8, 9, 10].forEach(function(v){ city[v] = tile1; });
[4, 5, 6, 11, 12, 13].forEach(v => city[v] = tile2);
console.log(city);
For older browser check polfill option of forEach method.

Related

leaflet and chroma.js .domain arguments not working

I am trying to incorporate chroma.js into my leaflet map so that i can toggle between quantiles, equal interval, and k-means, but the second and third argument for the domain function does not change anything
var colorScale = chroma.scale('YlGnBu').domain(voterList, 3, 'quantiles');
Here is the full code for the function
this.getRegionItemColor = function(item) {
var regionData = Mapbook.getRegionData();
var voterList = Mapbook.getColorScheme();
var colorScale = chroma.scale('YlGnBu').domain(voterList, 3, 'quantiles');
if (!_.isUndefined(item)) {
var voters = item.voters,
minVoters = regionData.min_voters,
maxVoters = regionData.max_voters;
var alpha = colorScale(voters);
return alpha;
}
else {
return 0;
}
}
Does anyone know why changing the number of buckets or classification method does not change anything?
Strange... I looked into it and I do think there is a problem with the library. Let's consider a very simple and documented example.
If you look at the documentation on github, here is what is written (https://github.com/gka/chroma.js/wiki/Color-Scales):
// Calling .domain() with no arguments will return the current domain.
chroma.scale(['white', 'red']).domain([0, 100], 4).domain() // [0, 25, 50, 75, 100]
When I do the same, however, this returns [0,100] (and not [0, 25, 50, 75, 100]); as you said, the second argument has not changed anything. You may want to flag that behavior as a bug on the plugin github page. Unless someone has a good explanation?
I was having the same problem, then I realized that at the time I defined 'ColorScale', my domain was not yet populated. are you certain that 'voterList' had your dataset in it at the time you defined ColorScale?

Got an index that I need to match with another array

So I have a bar chart with for example this array:
[12, 32, 42, 32, 43, 0, 0, 0, 5, 0, 0, 0]
So I have this array from markers from a google map with a length of 6, so from index 0 to 5.
I have an highlight event on the bar chart that when fired, it gives me the pointindex. I use the pointindex to get the marker from the google maps array, like: "gmap.markers[pointindex]". This works fine for the first 5 values from the bar chart array. but the ninth value from the bar chart array has the pointindex 8, but my google maps array only has 0 till 5 as index. So it doesn't work anymore. Basicly the pointindex 8 is basicly the index 5 from the google maps marker array.
This problem would also occur with as example these values.
Bar chart array: [12, 32, 42, 32, 43, 0, 7, 0, 5, 0, 0, 0]
Google map marker array with a length of 7, so index from 0 to 6.
I have this code for the highlight of a bar in the chart, this event is fired and I do stuff with the marker to highlight a marker(basically change the icon.
chart.bind('jqplotDataHighlight',
function (ev, seriesIndex, pointIndex, data) {
marker = gmap.markers[pointIndex];
if (marker !== null && marker !== undefined) {
marker.setIcon('https://maps.gstatic.com/mapfiles/ms2/micons/blue-dot.png');
}
}
);
As I explained when there is empty data in a pointindex of the bar chart array, the index of the bar doesn't match anymore with the index of the google marker.
I thought in my head to copy the bar chart array to a new array and remove all values that contain "0". and than compare the value from the bar chart array with the new array without "0" values's to see what the index is in the new array. So that it would match again with the google map marker index. But then you have the problem that if the bar chart array has 2 values that are the same, then this method doesn't work anymore.
Does anyone know a solution to this, in my head the problem is really simple, but I can't figure it out in code.
So #Nina's solution works in principle but not in terms of UI interaction.
Basically you need to see if the bar that was clicked has a value, and if it does, which index it maps to in Nina's filtering solution. Once you have the index that the value lies in from the filtered array, you can map that to your markers array.
To do this:
I think your best bet is, when building the bar chart to maintain an array with an object that is like { filteredIndex: N }. This array will be same length as the bar chart and tells you which index it maps to in the filtered array. If the data is 0, then the filteredIndex will be null.
You can do this simply by iterating your data and pushing the value to the filtered array if it's value is greater than 0, and maintaining the index, in a separate mapping array.
Thanks #Alex for the idea, and thanks #NinaScholz for the help, but I think you misunderstood my question, I know it was a vague question, sorry.
I have solved it by doing this.
when the page is loaded I do this:
var barArray = PF('dataChart').plot.data[0];
var mappingArray = new Array(barArray.length);
var j = 0;
for (var i = 0; i < barArray.length; i++) {
if (barArray[i] !== 0) {
mappingArray[i] = j;
j++;
} else {
mappingArray[i] = null;
}
}
And the listener now does this:
chart.bind('jqplotDataHighlight',
function (ev, seriesIndex, pointIndex, data) {
marker = gmap.markers[mappingArray[pointIndex]];
if (marker !== null && marker !== undefined) {
marker.setIcon('https://maps.gstatic.com/mapfiles/ms2/micons/blue-dot.png');
}
}
);
So basically I make a new array that is as long as the chart array, if the value from the chart array has a value that is not 0, I set the value of this index in the mappingArray to a counted up index, that matches with the google markers index. If this can be done better, please do tell!
Here is the solution with the preserved index and the right index for sparse access.
var barChart = [12, 32, 42, 32, 43, 0, 7, 0, 5, 0, 0, 0],
filtered = [];
barChart.forEach(function (a, i) {
a && filtered.push({ value: a, index: i });
});
document.write('<pre>' + JSON.stringify(filtered, 0, 4) + '</pre>');

Style line graph with ranges in RickshawJS

I'm trying to build a graphing system whereby line plots which are within a range, are dotted lines and those either exceeding or not reaching the range are drawn in solid lines. That is, in the following array [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], if my range is [4,7] I would have 2 sets of points: my data which is in range (dotted line): [null, null, null, 4, 5, 6, 7, null, null, null]; and my data which is out of range (solid line) [1, 2, 3, null, null, null, null, 8, 9, 10].
I thought I would do this by rending two line plots for each dataset. One with a dotted style and one with a solid style. To achieve this, I tried a POC to create a gap in my line plots.
I thought I might do this by deleting elements in the data series before sending it to be rendered (http://jsfiddle.net/drewsonne/tczooff2/):
var random = new Rickshaw.Fixtures.RandomData(150);
for (var i = 0; i < 150; i++) {
random.addData(seriesData);
}
// Create empty part of graph
for (var i = 70; i < 100; i++) {
delete seriesData[0][i];
}
But I seem to get an straight interpolated line in my graph where the removed elements are.
Is it possible to render a partial line in RickshawJS, or any other method which would achieve my range styling?
I appreciate I may even have to break the plots up into contiguous lines. This would require 3 different plots for my above example. If I do this, I still need to draw a partial plot. Any empty elements in a data set error out in rickshawjs.
EDIT: Solution was to change my above code to remove the 'y' value only, while retaining the 'x' value:
// Create empty part of graph
for (var j = 10; j < 100; j++) {
seriesData[0][j].y = null;
}
Don't know of it helps but I only found that you can end the line prematurely by setting a value to zero:
seriesData[0][75] = 0;
results in red line being drawn only half the normal way.
Looks like gaps are supported only in some types of graphs: http://code.shutterstock.com/rickshaw/examples/gaps.html

Need a solid way to set relational indices for object polygons drawn in a canvas element

Okay this is going to be hard to explain. So bear with me.
Im having less of a problem with the programming, and more a problem with the idea behind what Im trying to do.
I have a grid of triangles. Ref: http://i.imgur.com/08BPHiD.png [1]
Each triangle is it's own polygon on a canvas element that I have set as an object within the code. The only difference between the objects is the coordinates that I pass through as parameters of a function like so:
var triCoordX = [1, 2, 3, ...];
var triCoordY = [1, 2, 3, ...];
var triCoordFlipX = [1, 2, 3, ...];
var triCoordFlipY = [1, 2, 3, ...];
var createTri = function(x, y, z) {
return {
x: x,
y: y,
sides: 3,
radius: 15,
rotation: z,
fillRed: 17,
fillGreen: 17,
fillBlue: 17,
closed: true,
shadowColor: '#5febff',
shadowBlur: 5,
shadowOpacity: 0.18
}
};
for (i = 0; i < triCoordX.length; i++){
var tri = new Kinetic.RegularPolygon(createTri(triCoordX[i], triCoordY[i], 0));
}
for (i = 0; i < triCoordFlipX.length; i++){
var triFlip = new Kinetic.RegularPolygon(createTri(triCoordFlipX[i], triCoordFlipY[i], 180));
}
Now what Im trying to do exactly is have each object polygon be able to 'recognise' its neighbors for various graphical effects.
How I propose to do this is pass a 4th parameter into the function that I push from another array using the for loop that sets a kind of "index" for each polygon. Also in the for loop I will define a function that points to the index 'neighbors' of the object polygon.
So for instance, if I want to select a random triangle from the grid and make it glow, and on completion of a tween want to make one of it's neighbors glow I will have the original triangle use it's object function to identify a 'neighbor' index and pick at random one of its 3 'neighbors'.
The problem is with this model, Im not entirely sure how to do it without large amounts of bloat in my programming, or when I set the function for the loop, to set a way for the loop to intuitively pick the correct index numbers for what are actually the triangle's neighbors.
If all of that made sense, Im looking for any and all suggestions.
Think of your triangles as being laid out in a grid with the triangle in the top left corner being col==0, row==0.
Then you can find the row/col coordinates of the 3 neighbors of any triangle with the following function.
Ignore any neighbors with the following coordinates because the neighbors would be off the grid.
col<0
row<0
col>ColumnCount-1
row>RowCount-1
Example code (warning...untested code--you may have to tweak it):
function findNeighbors(t){
// determine if this triangle's row/col are even or odd
var evenRow=(t.col%2==0);
var evenCol=(t.row%2==0;
// left neighbor is always the same
n1={ col:t.col-1, row:t.row };
// right neighbor is always the same
n2={ col:t.col+1, row:t.row };
// third neighbor depends on row/col being even or odd
if(evenRow && evenCol){
n3={ col:t.col, row:t.row+1 };
}
if(evenRow && !evenCol){
n3={ col:t.col, row:t.row-1 };
}
if(!evenRow && evenCol){
n3={ col:t.col, row:t.row-1 };
}
if(!evenRow && !evenCol){
n3={ col:t.col, row:t.row+1 };
}
// return an array with the 3 neighbors
return([n1,n2,n3]);
}

How to change properties of element in JSXGraph?

Suppose, I have the following piece of code:
var brd2 = JXG.JSXGraph.initBoard('box2', {boundingbox: [-8.75, 2.5, 8.75, -2.5]});
var ax2 = brd2.create('axis', [[0,0],[1,0]]);
How can I change second point of axis?
Something like ax2.setSecondPoint([2,0])?
In general, how can I set property of any element?
Thank you.
Axis has two properties which names are self-explanatory: point1 and point2.
You can use setPosition method on any of them, e.g.
ax2.point2.setPosition(JXG.COORDS_BY_USER,[2,0])
Now there is one catch: you will not see this change on the chart unless you set needsRegularUpdate property of the axis object to true. Finally, to refresh the chart you should execute fullUpdate() method on the board variable. The whole looks like this:
var brd2 = JXG.JSXGraph.initBoard('box2', {boundingbox: [-8.75, 2.5, 8.75, -2.5]});
var ax2 = brd2.create('axis', [[0,0],[1,0]],{needsRegularUpdate:true});
ax2.point2.setPosition(JXG.COORDS_BY_USER,[2,0]);
brd2.fullUpdate();
References:
http://jsxgraph.uni-bayreuth.de/docs/symbols/JXG.Point.html#setPosition
http://jsxgraph.uni-bayreuth.de/wiki/index.php/Options (search for "special axis options")
Now to change properties like fixed, visible, etc. you should use setAttribute method (setProperty is deprecated). Example:
// Set property directly on creation of an element using the attributes object parameter
var board = JXG.JSXGraph.initBoard('jxgbox', {boundingbox: [-1, 5, 5, 1]};
var p = board.create('point', [2, 2], {visible: false});
// Now make this point visible and fixed:
p.setAttribute({
fixed: true,
visible: true
});
Source:
http://jsxgraph.uni-bayreuth.de/docs/symbols/JXG.GeometryElement.html#setAttribute
Last but not least a simple formula:
a + b = c
where:
a = using JavaScript debugging tools in browsers to investigate object properties
b = checking documentation for products you use
c= success :)

Categories