I have an array of Nodes 'flags', and I want to set my object's position at the first object in that array, it works and the object actually gets positioned as intended, but when I make the comparison it fails and logs 'NO'.
The line of code that sets the position works, but the comparison fails, what's wrong here?!
start: function () {
this.node.position = this.flags[0].position;
this.movement();
},
movement: function() {
if (this.node.position == this.flags[0].position) { // Problem
console.log("YES");
}
else {
console.log("No");
Update:
When I do it like this it works:
if (this.node.position.x == this.flags[0].position.x) // or position.y
Well if you write javascript here (and it looks like you do) there're two things you should know:
You can't compare objects with == out of the box
({"a":1} == {"a":1})
Will return false (you may try it yourself in your browser.
As a workaround you could do something like:
function posCompare(p1, p2){
return p1.x === p2.x && p1.y === p2.y;
}
Then use it instead of == for positions
See how I use === instead of ==? Second thing to know is Use only ===. You can learn the difference Which equals operator (== vs ===) should be used in JavaScript comparisons? but I'd keep away from == anywhere. It's slower, it may cause strange errors here and there - just don't use it at all
Related
So I'm just getting to grips with node-red and I need to create a conditional global function.
I have two separate global.payloads set to a number value of either 0 or 1.
What I need to happen now is, if global.payload is equal to value 1 then follow this flow, if it is equal to value 0 then follow this one.
I'm just a little confused with the syntax for the function statement. Any help gratefully appreciated.
Since you haven't accepted the current answer, thought I'd give this a try.
I think this is what you need to handle inputs from two separate global contexts. I'm simulating them here with two separate inject nodes to demonstrate:
The checkconf inject node emits a 1 or a 0. Same for the meshstatus node. Substitute your real inputs for those inject nodes. The real work is done inside the function:
var c = context.get('c') || 0; // initialize variables
var m = context.get('m') || 0;
if (msg.topic == "checkconf") // update context based on topic of input
{
c = {payload: msg.payload};
context.set("c", c); // save last value in local context
}
if (msg.topic == 'meshstatus') // same here
{
m = {payload: msg.payload};
context.set('m', m); // save last value in local context
}
// now do the test to see if both inputs are triggered...
if (m.payload == 1) // check last value of meshstatus first
{
if (c.payload == 1) // now check last value of checkconf
return {topic:'value', payload: "YES"};
}
else
return {topic:'value', payload: "NO"};
Be sure to set the "topic" property of whatever you use as inputs so the if statements can discriminate between the two input. Good luck!
You can use the Switch node to do this, rather than a Function node.
With the new ASC 2.0 compiler I get warnings when I code like below:
// (_achievementsFromServer is an Array)
while(item=_achievementsFromServer.pop())
{
// do something with item here
}
The warning reads: "Assignment within conditional. Did you mean == instead of =?"
While in general I appreciate all warnings from the compiler, I'd like to suppress this one in this case because I did not mean == here. I want to pop all items in the array and do something with it until the array is empty.
while( (item=_achievementsFromServer.pop())==true )
seems to work but looks a bit confusing. Any other ideas?
This may seem better.
while(_achievementsFromServer.length > 0) {
var item:Object = _achievementsFromServer.pop();
}
Just like removeChild
var d:DisplayObjectContainer;
while(d.numChildren > 0) {
d.removeChildAt(0);
}
While I was hoping for some other way, I think #AmyBlankenship improved my own suggestion:
while((item=_achievementsFromServer.pop())!=null)
{
//....
}
It's clear and understandable what's going on, and doesn't rely on checking the length of the Array on every iteration.
Googling some more I found a compiler option -compiler.warn-assignment-within-conditional that could be set to false but then you won't be warned anywhere in your project anymore. And I'm not so confident that I never accidently type = instead of ==, so that's not a good solution I think.
I'm looking at the as3delaunay library and most of the code is clear to me. This part is not, however (note the line that I put preceded with an arrow):
public function circles():Vector.<Circle>
{
var circles:Vector.<Circle> = new Vector.<Circle>();
for each (var site:Site in _sites)
{
var radius:Number = 0;
var nearestEdge:Edge = site.nearestEdge();
=======>> !nearestEdge.isPartOfConvexHull() && (radius = nearestEdge.sitesDistance() * 0.5);
circles.push(new Circle(site.x, site.y, radius));
}
return circles;
}
For reference, isPartOfConvexHull() is found in Edge.as and looks like this:
internal function isPartOfConvexHull():Boolean
{
return (_leftVertex == null || _rightVertex == null);
}
What does !nearestEdge.isPartOfConvexHull() do? Does that mean that the radius = nearestEdge.sitesDistance() * 0.5 only executes if false is returned from the call to isPartOfConvexHull()? Does that stop execution of any other code?
It is equivalent to:
if (!nearestEdge.isPartOfConvexHull()) {
radius = nearestEdge.sitesDistance() * 0.5;
}
In the following line:
var b:Boolean = expression1 && expression2;
expression2 will not be evaluated if expression1 is false because we already know the final result: b = false.
Now in the following line:
expression1 && expression2;
The same thing happens except the fact that we are not assigning the result to a variable.
And this is exactly what happens in the line you are asking about where !nearestEdge.isPartOfConvexHull() is the first expression and (radius = nearestEdge.sitesDistance() * 0.5) is the second expression.
To extends #sch answer with some explanations (I didn't knew if editing answer to almost double it was ok).
This is based on lazy execution of the interpreter. If (!nearestEdge.isPartOfConvexHull()) is False then there's no need to execute the second part of the AND statement to know it'll be False, then it's left unexecuted. If it's true the evaluation of the complete statement is needed (and then done) to tell wether or not this boolean is True. So this is equivalent to an if statement.
TMHO this is bad code since it's to much condensed and hard to understand.
Actually I've parsed a website using htmlparser and I would like to find a specific value inside the parsed object, for example, a string "$199", and keep tracking that element(by periodic parsing) to see the value is still "$199" or has changed.
And after some painful stupid searching using my eyes, I found the that string is located at somewhere like this:
price = handler.dom[3].children[3].children[3].children[5].children[1].
children[3].children[3].children[5].children[0].children[0].raw;
So I'd like to know whether there are methods which are less painful? Thanks!
A tree based recursive search would probably be easiest to get the node you're interested in.
I've not used htmlparser and the documentation seems a little thin, so this is just an example to get you started and is not tested:
function getElement(el,val) {
if (el.children && el.children.length > 0) {
for (var i = 0, l = el.children.length; i<l; i++) {
var r = getElement(el.children[i],val);
if (r) return r;
}
} else {
if (el.raw == val) {
return el;
}
}
return null;
}
Call getElement(handler.dom[3],'$199') and it'll go through all the children recursively until it finds an element without an children and then compares it's raw value with '$199'. Note this is a straight comparison, you might want to swap this for a regexp or similar?
I am trying to sort big array using actionscript 3.
The problem is that i have to use custom sorting function which is painfully slow and leads to flash plugin crash.
Below is a sample code for custom function used to sort array by length of its members:
private function sortByLength():int {
var x:int = arguments[0].length;
var y:int = arguments[1].length;
if (x > y){
return 1;
}else if (x < y){
return -1;
}else{
return 0;
}
}
Which is called like this:
var txt:Array = ["abcde","ab","abc","a"];
txt.sort(sortByLength);
Please advise me how can this be done faster ?
How to change application logic to avoid Flash plugin crashes during sorting ?
try to use strong typing whenever possible, here tell your function that you are waiting two strings.
you could rewrite your function in two way one fastest than the other if you know that all your element are not null:
function sortByLength(a:String, b:String):int {
return a.length-b.length // fastest way not comparison
}
and if you can have null check for it (this one will put null in front of all element):
function sortByLengthWithNull(a:String, b:String):int {
if (a==null) return -1
if (b==null) return 1
return a.length-b.length
}
If you need super-fast sorting, then it might be worthwhile not using an array at all and instead using a linked-list. There are different advantages to each. Primarily, with a linked-list, index-access is slow, while iterating through the list is fast, and linked-lists are not native to AS3 so you'll have to roll your own.
On the upside, you may well be able to use some of Polygonal Labs' code: http://lab.polygonal.de/as3ds/.
Sorting is very, very fast for nearly-sorted data with a linked list, as this article discusses: http://lab.polygonal.de/2007/11/26/data-structures-more-on-linked-lists/.
This solution gives you lots more work, but will eventually give you lots more sort-speed too.
Hope this helps.
-- additional --
I noticed your question in the comments of another answer about "One question however is unanswered - how to perform greedy computations in Flash without hanging it?"
For this, essentially the answer is to break your computation over multiple frames, something like this:
public function sort():void
{
addEventListener(Event.ENTER_FRAME, iterateSort);
}
private function iterateSort():void
{
var time:int = getTimer() + TARGET_MILLISECONDS_PER_FRAME;
var isFinished:Boolean = false;
while (!isFinished && getTimer() < time)
isFinished = continueSort();
if (isFinished)
removeEventListener(Event.ENTER_FRAME, iterateSort);
}
function continueSort():Boolean
{
... implement an 'atom of sort' here, whatever that means ...
}
sortByLength should have two parameters, shouldn't it? I guess that's what you mean by the arguments array...
This looks fine to me, unless arguments is not a local variable, but instead a member variable, and you're just looking at its [0] and [1] elements on each function call. That would at least produce undesired results.