Name Firebase child as sequence array - javascript

I want to use Fusionchart to read my Firebase data and create a chart in my web app. but my Firebase DB has a wrong structure, so the Fusionchart can't get data (my Firebase config is right).
Following is the code that I write data to Firebase, num is a value increased in each loop. But as shown in the attached picture, the child's name is not added as a sequence number.
Another question is I don't want the unique key inside the child 1, just six various inside the child one is ok.
Any suggestions will be appreciated.
firebase.database().ref('testdata/User1').child(num).push({
x: posX,
y: posY,
MaxSpeed: maxSpeed,
steps: counter,
time: Timeperiod /1000,
speed: SpeedRecord,
});

If you don't want the push ID inside your pseudo-numeric keys, call set instead of push.
So:
firebase.database().ref('testdata/User1').child(num).set({
x: posX,
y: posY,
MaxSpeed: maxSpeed,
steps: counter,
time: Timeperiod /1000,
speed: SpeedRecord,
});
Your other problems seems (it's impossible to be certain, since you didn't include the code for the increment) to come from the fact that num is a string. If that is indeed the case, increment it with:
num = String(parseInt(num) + 1);
Using such numeric keys is an antipattern in Firebase though, so I'd usually recommend against using them. If you must, at least pad them til a certain length, so that you can sort/filter on them easily.
Something as simple as:
num = String(parseInt(num) + 1).padLeft(5, "0");
Will work on all modern browsers, and ensures that all keys-that-look-like-numbers-but-behave-like-strings will show up in the order you expect.

Related

Ember Computed Property Slow and Inconsistent

I have an app that displays videos and allows users to rate the videos. An average rating and the number of times the video has been rated are displayed beneath it. To calculate these I have added computed properties to each model. The average property relies on the sum and length computed properties.
/*global Ember */
import DS from 'ember-data';
export default DS.Model.extend({
title: DS.attr('string'),
url: DS.attr('string'),
ratings: DS.hasMany('userrating'),
users: DS.hasMany('user'),
rated: DS.attr('boolean'),
// maps through ratings objects and pulls out the rating property
// returns an array of integers that represent all of one videos ratings
numRatings: Ember.computed.mapBy('ratings', 'rating'),
// returns the sum of a videos ratings
sum: Ember.computed.sum('numRatings'),
// returns the number of ratings a video has
length: Ember.computed('numRatings', function () {
return this.get('numRatings').length;
}),
// returns true if the video has only been rated once
// this is used to determine if '1 user' or '2 users' etc.
// should be displayed
one: Ember.computed('length', function () {
if (this.get('length') === 1) {
return true;
}
}),
// returns the average rating of a video
avg: Ember.computed('length', 'sum', function () {
return Math.round(this.get('sum') / this.get('length'));
})
});
I have noticed that sometimes the sum is displayed in place of the average. This usually happens only for a second and then the average correctly displays, but every once in a while the average does not display. Today, all videos except for one were displaying correctly, but that one video was displaying ’33/5’ as the average rating.
Why is this happening?
Should I not build Ember computed properties to rely on each other?
Is this just a problem with the browser being slow? I am loading a bunch of videos and images.
I am pretty new to web development in general and this is my first Ember app.
Thanks!
It's difficult to really know where there may be performance issues without seeing your entire architecture, but I can see the following:
You have a relationship with userrating and user models associated with your video model
Both your sum and length computed properties are based off of another computed value, which itself is performing a map to pull out rating values out of ratings objects
You have another computed watching length, that is purely determining the plurality of the word "user" somewhere else in the code
Lastly, you have an avg computed that is watching those other two computed properties as well
Now, again, I can't really provide an exact answer why, but here are a few suggestions to (maybe) lighten to load on your model here.
Eliminate the one computed altogether. You can perform this calculation on the component/controller side if you really want to know if a single one is selected, but you can do something else like Ember.computed.equal('numRatings', 1)
length property can be eliminated in favour of this.get('numRatings.length')
Have avg watch just numRatings so that it will only recalculate if that particular number changes, because you already know that sum will update as well anyway, so might as well reduce the number of observed properties
That said, if it's still acting wonky, you may want to make sure the data found in userrating entries are correct. If it still feels slow or takes its time calculating, you can also try changing mapBy into a plain vanilla JS for loop, as those are significantly faster (albeit less readable) than using Array methods.
Good luck!
length: Ember.computed('numRatings', needs to be length: Ember.computed('numRatings.[]', -- you need to observe the length of the array, not the array itself (which will only raise a flag if the value changes as a whole)
you can also use the alias property -- Ember.computed.alias('numRatings.length')

How to Avoid or Test Randomness in Functional Programming

I started to make a dungeon-game that creates randomly new dungeons.
Currently I write the function createRoom that returns a new room object based on the arguments. This function is called in createDungeon, but it receivs random parameters there.
function createRoom (width = 1, height = 1, topLeftCoordinate = {x: 0, y: 0}) {
return {
width,
height,
topLeftCoordinate
}
}
function createDungeon (numberOfRooms, rooms = []) {
if (numberOfRooms <= 0) {
return rooms
}
const randomWidth = getRandomNumber(5, 10)
const randomHeight = getRandomNumber(5, 10)
const randomTopLeftCoordinate = {x: getRandomNumber(5, 10), y: getRandomNumber(5, 10)}
return createDungeon (
numberOfRooms - 1,
rooms.concat(Room.create(randomWidth, randomHeight, randomTopLeftCoordinate))
)
}
I don't know if this is the right why, because I don't how to test createDungeon. I can only test if this function retuns an array and the length of the array.. Is this enough or is there a design pattern for the randomness?
Well, first off I'm assuming that your getRandomNumber is in fact a pseudorandom seed-based generator with a global seed. To make it more in the spirit of true FP, you'd need to make the seed/generator passing and mutation explicit, but that's not something you absolutely have to do.
Now, the answer depends on what you want to test. If you need to make sure that your random generation provides the same values for a given seed (which is important when e.g. you want to have "world seeds" like Minecraft does), then it's enough to hardcode the seed and then proceed with known output.
An important note is that when using a global random number generator, every number "drawn out" of it will impact the future numbers. This means that if you change your test code later on to include some other numbers before the previous test cases, your hardcoded values will completely mismatch. You could mitigate that by ensuring that all independent test runs start with a fresh generator.
If you want to test the behavior in a more "reasonable" way, that is, whether the function generally behaves ok, you'll need to use more seeds and run it multiple times. Now whether the seeds are themselves random or hardcoded doesn't matter; the important difference is that your validation rules now can't test for specific value equality, but instead need to check for boundaries or some other range criteria.
In general, test execution should be deterministic and repeatable, so dealing with randomness in tests should be avoided (there's a great book, Lasse Koskela's "Effective Unit Testing", where you can find out how to deal with randomness in tests, among many other issues).
This means, for example, that if you write a test to check what is the result of createDungeon(3), the results of that call should always be the same, so the assertions you make about that result are always valid.
May I suggest a small refactor, in your example: the random number generator should be passed as an argument to createDungeon:
function createDungeon (numberOfRooms, randomGenerator, rooms = []) {
...
const randomWidth = randomGenerator.getRandomNumber(5, 10)
...
}
In your tests, you pass a test double (a mock object) for your randomGenerator, previously set up to return some known values. You can use some mock framework like JsMockito, and then you can just do something like:
generator = mock(RandomGenerator);
when(generator).getRandomNumber(5,10).thenReturn(8);
// run the test
generateDungeon(3, generator);
// verify results
assert(...)

JS, DOM. Delete several elements from DOM using user intput value

Example on Codepen below. Can anybody explain as simple as posible how to delete a number of elements from DOM based on a user input value (just an integer). I have a path(SVG curve). User specifies a number of steps(dots) to reach the end point of the path. Then ship will travel to the end point, after some event ( for test I'm using click event ). User will specify a number of steps per move for each event ( event done ship start moving ). And by moving i want to delete dots on the pass that are left behind.
var trigger = window.addEventListener('click', function(){
var steps = parseInt(prompt("Select Number Of Steps Per Move "),10);
var positionVal = parseFloat(window.getComputedStyle(el,null).getPropertyValue("motion-offset"));
el.animate([
{ motionOffset: positionVal + "%" },
{ motionOffset: positionVal + 100/(userValue - 1)*steps + "%" }
],
{duration: 5000,
direction: 'alternate',
fill: 'forwards',
iterations: 1,
easing: 'ease-in-out'
});
function deleteThis () {
dotsArray.splice(positionVal, steps)
var dots = document.getElementsByClassName("dots");
for (i=0;i<steps;i++) {
dots[i].remove();
}
}
window.setTimeout(deleteThis,3000);
});
Codepen Example
If you want to remove DOM elements:
for (i=0;i<steps;i++) {
dotsArray[0].remove();
dotsArray.splice(0,1);
}
Sounds like you're asking how to remove elements from the DOM, which happen to be stored in an Array.
The Array that happens to be holding some DOM elements and the DOM/elements themselves are completely unrelated concepts. There will be no native Array method for dealing with the DOM, because Arrays are not a DOM concept, they are a general programming construct of JS. They could be holding DOM elements, Strings, Numbers, other Arrays, Objects, null Objects, or a combination of all the above...or more. There is nothing about Arrays that is specific to the DOM...that just happens to be what you have shoved into that Array.
For that you're simply gonna need to loop through the Array and remove the elements. I'd recommend making a function to do so if you're gonna be doing it a lot:
// removes the elements in the Array from the DOM, then removes them from the Array
function removeArrElemsFromDOM(arr, start, howMany)
{
for (var i=start; i<start+howMany; i++)
arr[i].parentNode.removeChild(arr[i]);
arr.splice(start, howMany);
}
You'd use like removeArrElemsFromDOM(myArray, 0, 2); would remove the first 2 elements of the array from the DOM (and also then cut them from the Array as well).
JSFiddle showing it working

MongoDB custom sorting with the other values?

I'd like to be able to sort this collection according to the following attributes of each item.
var distance1 = { velocity : 100, time: 20, rank: time*velocity};
var distance2 = { velocity : 50, time: 25, rank: time*velocity};
var distance3 = { velocity : 300, time: 10, rank: time*velocity};
collection.insert([distance1, distance2, distance3]);
So basically rank them in accordance of 'distance' (time*velocity) in ascending order.
The list should end up as this;
distance2
distance1
distance3
However, the rank needs to be derived from the distance and velocity containers, since otherwise you'd run into a problem when the user changes the values;
distance1.set(time= "1");
distance1.set(velocity = "1");
distance2.set(time= "100");
distance2.set(velocity = "20");
distance3.set(time= "10000");
distance3.set(velocity = "20000");
Which should the rank to;
distance1
distance2
distance3
But will not do so if the rank is static.
How can I make use of MongoDB's meta and sorting functionality to allow a dynamic ranking algorithm based on user input? Kind of like how Reddit uses upvotes to determine where a page ranks.
EDIT: holy shit fixed a dumb physics mistake
The most efficient approach would be to update the rank field when you change the values in your application code (i.e. don't allow time and velocity to be set without also recalculating the rank). You can then add an appropriate index (or indexes) including the rank field to support your common queries (see Optimizing MongoDB Compound Indexes for some helpful background on creating indexes).
You could also compute rank dynamically via a query with the aggregation framework, but that would involve a very inefficient recalculation for all matching documents in the collection to determine result order.

Is Canvas' drawImage method truly syncronous?

I'm implementing a menu system for my game using canvas (for certain performance reasons I cannot use HTML/CSS to make the menus). I have the menu configured using JSON and menuComponent objects are created with their respective properties (x, y, width, height, imagePath, etc). I have a menu loader which then iterates over the component objects and calls the componentObjects' draw method (all images wait for their onload event to fire first, of course).
Anyway, I expect my images to be drawn in the order that their draw method is called so that they overlap in the correct order. The majority of the time this behaviour is correct but occasionally they will draw in the wrong order.
My question is - can I trust Canvas to draw images in the order the drawMethod is called for those images? Say I have image A which is, for example, 10MB and image B which is 10kb. If I call draw image A and then draw image B then is there a chance that image B will load first because it's a smaller image?
I was trying to be smart with my code (having nested components inside my component objects and recursively call draw methods) so it's possible there's some race conditions in my code, I just want to confirm the above behaviour is correct. If I add logic to force my objects to wait until a ready flag is set then it seems to work. But unfortunately that slows up my menus load time.
To put a formal answer to this post -
In the end I simplified my solution to use one menuLoader object which has an array of hashes for each image to be drawn (containing x, y, imagePath, ready flag). I call a create components method which builds up these hashes with the ready flag set to false by default. I set an onload event for each image to set its respective ready flag to true.
After create components has finished executing I use setInterval to spin until all flags have been set to true. Once this condition is met I iterate through my array of hashes again and call the draw method for each image.
Man I've faced same problem and have been stucked with it for about three days. And I figured one interseting thing. Please look though this code snippet and supply me with your thoghts on it.
final ResourceManager rm = new ResourceManager(1000, 1000);
rm.loadImgResource(LandCardResources.INSTANCE.getMeadow(), "meadow", 0, 0);
rm.loadImgResource(LandCardResources.INSTANCE.getHellHorseKnight(), "knight", 150, 150);
Resource manager is an object representing BackBufferCanvas that holds all images in its context (like simple image sprite). Constructor is also responsible for adding this Backbuffer to RootPanel, so we can determine thats everything worked like we expected. After that I'm adding my main canvas to root trying to draw on it from backBufferCanvas using perfectly working ResourceManager instance.
canvas.setWidth(500 + "px");
canvas.setHeight(500 + "px");
canvas.setCoordinateSpaceWidth(500);
canvas.setCoordinateSpaceHeight(500);
RootPanel.get().add(canvas);
rm.drawImageFromMetaDb(ctx, 0, 0, 100, 100, 0, 0, 100, 100);
rm.drawImageFromMetaDb(ctx, 150, 150, 100, 100, 50, 50, 100, 100);
And it never works. But if I for example add Button to rootPanel with handler that is responsible for rm.drawImage..... It will work perfectly when clicking this Button. Can't really understand why this is happening as backBufferCanvas is attached before mainCanvas so logic must be already delayed.

Categories