Wednesday, May 15, 2013

The day true became false


I occasionally get to work on a module that heavily uses google closure.  I think the original architect wanted to use it since it because google provides a compiler and a pretty robust library for doing cross browser javascript.  I also like using closure when dealing with multiple people working on a large javascript project because the compiler can enforce some rules that keep certain bad code from being checked in (besides also enforcing a linter).

The particular issue I dealt with was "fun" because I wasted an entire day trying to track down a defect that at the surface appeared to be a cross browser issue.  One action would show a page in firefox, but it would show a blank page in chrome.

Initially, the strategy I took was looking at the ajax requests in developer tools and making sure that they were firing correctly at the right times.  After determining that the requests were being fired, I then tried to figure out why the callbacks for the requests were not being fired.

One thing to note was that we were able to reproduce the issue when we were using the minified code, but were not able to reproduce the issue when the code was un-minified.

So, we eventually got in a window.console.log spiral, where we would put a log in a closure library module, and compile the source, test it, and eventually say WTF, and rinse repeat...

At one point, my pair programming partner noticed that one of the variables in the xhrio.js library was not behaving correctly.

The source was this:

goog.net.XhrIo.prototype.send = function(url, opt_method, opt_content,
                                         opt_headers) {
...
    this.active_ = true;
    window.console.log('this.active_:', this.active_);
    // should log true
This code was logging true, then all of a sudden, it logged 0. We were baffled. Why was true turning into false! Even other functions were failing.
...
   window.console.log('this.isComplete', this.isComplete());
   // showed 0
   if (this.isComplete()) {
   }
I eventually decided to go straight to the minified source and find out what isComplete was doing:
var b=Zh(a),c;a:switch(b){case 200:case 201:case 202:case 204:case 206:case 304:case 1223:c=j;break a;default:c=l
I figured that somewhere in this file was a variable l, or a variable j that represented true, or false. Sure enough, at the top of the file, I saw this:
function e(a){throw a;}var h=void 0,j=!0,k=null,l=!1;

!0 === true, and !1 === false.

 I then figured that other code minifiers were doing this strategy. I looked at jQuery minified, and sure enough, everywhere was littered with !0 and !1 in the jQuery code in many truth checks and returns. I then figured that maybe google has already addressed this issue, so I filed an issue with them.

They told me that you have to wrap your module in a private scope: https://code.google.com/p/closure-compiler/wiki/FAQ#When_using_Advanced_Optimizations,_Closure_Compiler_adds_new_var
 What you do is pass a command line argument to the compiler.jar: --wrap-output "(function(){%output%})();"

 But I did some digging and had a daily WTF moment... We already had this wrap output, but it was removed a few months ago, because we created a separate closure module. I don't know the reasoning behind why this was removed, but I do think there should be an option to choose to minify special keywords, or even just to do the simple find/replace of true false with !0/!1.

Anyway, now you know that if you don't use wrap-output, you could be in for a lot of pain. All you need is a third-party library to not use the var keyword on simple variables.  If you don't use the var keyword, the variable will change the window scoped variable, which was where the closure minified variables were living.

If this for loop only went to 0 and never iterated greater than 0:
for(i=0; i < something.length; i++) {
   for(j=0; j < somethingelse.length; j++) {
     //...
   }
}
You would have a bad day trying to find out why true is now false...

Tuesday, April 16, 2013

Java testing with json

I recently wanted to write jUnit tests where I needed to have pre-constructed json in the test.
This gets very messy:

@Test
private void testAPI() {
    String json = "{\"someobject\":" +
              "{" +
              "\"attr1\": 123," +
              "\"attr2\": {" +
              // getting tired yet? ...
              "\"anotherattr\": \"foobar\"" +
              "}" + 
              "}" + 
              "}";
    // clear as mud, right?
    // test here...

This definitely was impeding the velocity of my test driven development progress.  Also, I felt like the next person who looks at this test is never going to want to maintain this test...

I know I have looked at a test and thought to myself, "too much scary syntax, why bother fixing it".

Well, after some quick googling, I found a solution that I like so far: http://www.adrianwalker.org/2011/12/java-multiline-string.html

This code provides the @Multiline java annotation and it takes the comment before a String declaration and shoves it into the string variable.

Now my code looks like this:

@Test
private void testAPI() {
    /**
{
   "someobject": {
       "attr1": 123,
       "attr2": {"anotherattr": "foobar"}
    }
}
    */
    @Multiline String json;
    // test here...

Do you think this look better?  I think so.

I was able to use this guys github to install the annotation in eclipse with minimal effort:
https://github.com/benelog/multiline

I don't think this should be used in production code, but I really like using it for test code.

Wednesday, February 6, 2013

Icon collision detection/resolution in javascript

Let's say you have an application that has several icons, like a desktop.  Since this application is web based, you get the coordinates of where to draw these icons from the backend through an API request.  Sometimes you can have coordinates that are in the same spot.  This can confuse your user because to them, they might think there is only one icon, when two or more are on top of each other.  This blog attempts to show possible solutions to this.

One approach to this problem is to try to draw colliding objects in a ramdom location around the original collision.  For example, if you had two objects drawn at (50, 50), you could choose a random radius between 0 and 1 (or some max radius), and a random angle to place between 0 and 2π.  Then you would take the angle and get the sin/cos values multiplied by the radius.  The code would look something like this.

// I'm sure there are point libraries out there but this is just a quick mockup.
var Point = function(x,y){ this.x = x, this.y = y; };
Point.prototype = {
 add: function(other) {
  return new Point(this.x + other.x, this.y + other.y);
 }
};

var MAX_RADIUS = 50;
function getNextPosition(point) {
 var theta = Math.random() * 2 * Math.PI;
 var radius = Math.random() * MAX_RADIUS;
 var x = Math.cos(theta) * radius;
 var y = Math.sin(theta) * radius;
 var offset = new Point(x, y);
 return point.add(offset);
};


Here is an example of running this code on 20 points.  I highlighted the original point red.
This is an ok attempt, but we can improve upon this.  What if we wanted the points to be drawn around the initial point in a circle.  Then when that circle is exhausted, we move to the next outer circle.  After filling out 2-3 circles, we fallback to the random point algorithm above.  Also when we go to the next circle, we double the number of points in the next circle since there is more space.

The mechanism we use to determine what part of the circle we are on is to use an iterator.  The iterator is calculated based on the number of times you have collided with this point.  We take this iterator and map it to the good old unit circle.



If we were walking around the unit circle, you could do what the above diagram does.  Ignoring the values divided by 3 or 6, you could pretend each point is walking around the unit circle in 8ths.  If you start at iterator 0, you want the value of angle 0, which yields cos(0) -> 1, sin(0) -> 0, or Point (1,0).  Then you move to iterator 2, which puts you at the angle, π/4, and yields the Point (√2/2, √2/2).  Iterator 3 yields the angle, π/2, Point (0, 1), etc.

So if you wanted to draw 4 points around the initial point using an iterator, the basic calculation looks like this:

var points_per_circle = 4;
var radius = 10; // the size of your icon
var current_circle = 1;
var angle = (iterator / points_per_circle) * (2 * Math.PI);
var x = Math.cos(angle) * radius * current_circle;
var y = Math.sin(angle) * radius * current_circle;

Given this calculation, next we need a way to determine if we have made a collision.  For this, I just use a hash and my key is the toString function on my Point object.  It needs to be defined otherwise you just get the string "[object]" when you call toString.

The data we store at the collision is our iterator.  We increment this number each time we have a collision.  This helps us remember the last iteration spot we used to calculate our point and will help us determine the next point.


var collision_hash = {};
var MAX_CIRCLES = 3;
var ELEMENT_RADIUS = 10;
Point.prototype.toString = function() { return '(' + this.x + ',' + this.y + ')'; };

function getNextPosition(point) {
 // increment that we have visited this point.
 collision_hash[point] = collision_hash[point] == undefined ? 1 : collision_hash[point] + 1;
 var iterator = collision_hash[point] - 1;

 if ( iterator == 0){
  return point;
 }
 
 var radius = ELEMENT_RADIUS; // the size of the element
 var current_circle = 1; // to extend the radius out to the next circle
 var points_per_circle = 4;
 while (iterator > points_per_circle && current_circle < MAX_CIRCLES) {
  iterator = iterator - points_per_circle;
  // goto the next circle and double the number of points
  current_circle++; 
  points_per_circle = points_per_circle * 2; 
 }

 // calculate the angle by slicing a circle up using the iterator
 var angle = (iterator / points_per_circle) * (2 * Math.PI);

 // if we have exhuasted 3 circles
 if (iterator > points_per_circle) {
  // randomize
  angle = Math.random() * 2 * Math.PI;
  radius = Math.random() * ELEMENT_RADIUS;
 }
 var x = Math.cos(angle) * radius * current_circle;
 var y = Math.sin(angle) * radius * current_circle;
 var offset = new Point(x, y);
 return point.add(offset);
};

Here are a few examples of after 4, then 12, then 28, then 40 collisions




This algorithm is fine, but it was brought to my attention that we don't have to have the wasted space in between.  It turns out that the better fit of things in a circle around an object is a hexagonal grid.  Also this algorithm doesn't keep track of the collision points as future collision points.  For example, if I collide with a point at (50,50) and return a point of (51, 50), I need to remember that I have visited (51,50) as well so that if I visit a different point that is (51,50) I draw a circle around that.

Drawing a hexagonal circle around a point is easy.  Just use π/3 to iterate around the circle.