My experience in the 2nd Tuenti Programming Challenge

by guido on 6/05/2012

This week I have been participating in the 2nd edition of the Tuenti Programming Challenge. I felt a little rusty on my return to top-level competition, but despite I started the competition three days late, I was able to reach level 14 (stats). Not so bad.

The problems I prefer are those with an obvious brute force solution, but that can take advantage of a particular algorithm or data structure. Most of the problems in this edition belong to this category except, perhaps, the challenge 12 which I did not like because I found it too much tricky.

The crazy croupier

The challenge I enjoyed the most was the number 13, the crazy croupier. It is kind of a classical problem with minor variations, where you have to determine how many shuffles you need in a deck of N cards in order to come back to the original position if you cut it at the position L.

The easy -brute force- solution is to iterate and count until the cards are in their original positions, which can be a time-consuming task when the number of the cards is big (up to 10^6 in this case).

The second approach is to convert it to a permutations problem. Once you know where the card 1..N is located after the first shuffle, you can determine the number of shuffles each individual card needs to come back to its location. The least common multiple of the individual results is the total number of shuffles needed.

Show me the code

Here it is (download). I do not know how many participants chose Java to solve the problems. What I have seen so far are solutions in Python (here, here) that seem more compact and PHP (here). It is a pity that the official ranking does not show the execution times :)

/**
 * Crazy Croupier - 2nd Tuenti Challenge - 12
 *
 * Example:
 * Number of cards: N = 10
 * Number of cards in the first set: L = 3
 * Cards: 10 1 4 2 8 5 6 7 3 9
 *
 * First set: 10 1 4
 * Second set: 2 8 5 6 7 3 9
 *
 * Shuffled set: 4 9 1 3 10 7 6 5 8 2
 */
public static void main(String[] args) {
  Scanner scanner = new Scanner(System.in);

  // read number of cases
  int cases = Integer.parseInt(scanner.nextLine());

  for (int i=1; i<=cases; i++) {
    // read N L, for example 10 6
    String line = scanner.nextLine();
    String[] arguments = line.split(" ");

    // N = cards in the deck
    int N = Integer.parseInt(arguments[0]);

    // L cards in the first bunch (where to cut the deck)
    int L = Integer.parseInt(arguments[1]);

    long result = processCase(N, L);
    System.out.printf("Case #%d: %d\n", i, result);
  }
}

/**
 * Returns the number of shuffles required to return the deck
 * to its original order.
 * The algorithm will calculate the number of iterations that
 * each individual card need to come back to its position. The
 * solution will be the least common multiple (lcm) of the
 * individual results.
 */
private static long processCase(int n, int cut) {
  int[] deck = new int[n]; // first deck shuffling result

  shuffleDeck(n, cut, deck);

  // cache source -> target positions for O(1) access
  final Map<Integer, Integer> permutations = new HashMap<Integer, Integer>();
  for (int i=0; i<deck.length; i++) {
    permutations.put(deck[i], i+1);
  }

  // cache to avoid multiple lcd calculations of the same num, O(1) access
  Set<Long> calculatedLcm = new HashSet<Long>();
  long lcm = 0;
  for (int i=0; i<deck.length; i++) {
    long numberPermutations = 1; // we already did the first shuffling
    int currentPosition = i+1;

    // still no at the original position
    while (currentPosition != deck[i]) {
      numberPermutations++;
      currentPosition = permutations.get(currentPosition);
    }

    if (calculatedLcm.contains(numberPermutations) == false) {
      lcm = lcm(lcm, numberPermutations);
      calculatedLcm.add(numberPermutations);
    }
  }

  return lcm;
}

/**
 * Shuffles the deck one time according to the algorithm.
 */
private static void shuffleDeck(int n, int cut, int[] deck) {
  int min = Math.min(cut, n-cut); // number of cards shuffled

  // shuffle two bunch of cards
  for (int i=0; i<min; i++) {
    deck[2 * i] = cut - i;   // 1st bunch
    deck[2 * i + 1] = n - i; // 2nd bunch
  }

  // put the rest of the cards in proper order, at the end
  for (int i=0; i<n - 2 * min; i++) {
    if (cut >= n / 2) { // first bunch is bigger
      deck[n - 1 - i] = i + 1;
    } else { // second bunch is bigger or equal
      deck[2 * min + i] = n - min - i;
    }
  }
}

/**
 * Least common multiple. Probably a more efficient approach can be
 * found but it is good enough.
 */
private static long lcm(long a, long b) {
  if (a == 0 || b == 0) {
    return Math.max(a, b);
  }
  return a * b / gcd(a, b);
}

/**
 * Greatest common divisor, see also {@link BigInteger#gcd(BigInteger)}
 */
private static long gcd(long a, long b) {
  long mod = a % b;
  return mod == 0 ? b : gcd(b, mod);
}

What do you think about it?

Talent is out there

I like these competitions (Google Code Jam, ACM ICPC, etc) a lot and I think it is a great (and cheap) opportunity for technological companies to attract and recruit talent. There are a lot of great coders hidden out there.

5 Comments

How to develop a Java REST client in 3 minutes

by guido on 2/03/2012

Some time ago I wrote a post about how to implement a REST API with Java (spanish). Today I am going to write about how to consume a REST API as a client. More specifically, I am going to use Digg API (probably not the best REST API out there) to search stories by a given keyword.

Show me the code

As it is a third party REST API, I am going to use the client framework provided by RESTEasy, that I find extremely easy to use.

You only have to add one dependency to your pom.xml:

  <dependency>
      <groupId>org.jboss.resteasy</groupId>
      <artifactId>resteasy-jaxrs</artifactId>
      <version>2.3.1.GA</version>
  </dependency>

And you are now ready to start coding. I think the Java code is self explanatory, so here it goes:

import org.jboss.resteasy.client.ClientRequest;
import org.jboss.resteasy.client.ClientResponse;

public class DiggClient {
    private static final String DIGG_SEARCH_ENDPOINT =
            "http://services.digg.com/{version}/search.search";

    public static void main(String[] args) throws Exception {
        ClientRequest req = new ClientRequest(DIGG_SEARCH_ENDPOINT);
        req
            .pathParameter("version", "2.0")
            .queryParameter("query", "health");

        ClientResponse<String> res = req.get(String.class);
        System.out.println(res.getEntity());
    }
}

But I do not want to parse a String…

You might have noticed that the response is converted to a String. In most cases an API will return a XML or a JSON representation of the data as response to the request. In these cases it is great to automatically convert the response into the objects in your Java data model.

For example, these are the domain classes representing (partially) the Digg search results:

class SearchResult {
    private int total;
    private Story[] stories;
    // ... getters/setters
}

class Story {
    private String id;
    private String title;
    // ... getters/setters
}

Digg results are offered as JSON, so you only need to add a Maven dependency to include the providers RESTEasy uses to handle JSON:

  <dependency>
      <groupId>org.jboss.resteasy</groupId>
      <artifactId>resteasy-jackson-provider</artifactId>
      <version>2.3.1.GA</version>
  </dependency>

The resulting Java code remains almost the same:

import org.jboss.resteasy.client.ClientRequest;
import org.jboss.resteasy.client.ClientResponse;

public class DiggClient {
    private static final String DIGG_SEARCH_ENDPOINT =
            "http://services.digg.com/{version}/search.search";

    public static void main(String[] args) throws Exception {
        ClientRequest req = new ClientRequest(DIGG_SEARCH_ENDPOINT);
        req
            .pathParameter("version", "2.0")
            .queryParameter("query", "health");

        ClientResponse<SearchResult> res = req.get(SearchResult.class);
        SearchResult result = res.getEntity();
        System.out.println(result.getTotal() + " matching stories found");
    }
}

Note: you need to annotate your domain Java classes as @JsonIgnoreProperties(ignoreUnknown=true) if the server returns any field that is not present in your domain Java classes.

What if you are using your own API?

If you already have developed your JAX-RS resources, I would suggest to use a proxy-based approach. Take a look at the JAX-RS client factory in Apache CXF, or how to share interfaces between client and server with RESTEasy. This way you reuse more code and makes your code maintenance easier.

Comments about other alternatives (Jersey, etc) are welcome.

No Comments

Auditing JPA entities with Hibernate Envers

by guido on 25/01/2012

In a recent project we had the need to keep a record of the changes made in every domain entity. That is, we need to insert a new record on an audit table every time an entity is created/updated/deleted.

This is not the first time this problem arises. I think this is a the case of a cross-cutting concern, that fits well into the aspect-oriented programming area. I have seen this very same problem in many different projects I have worked on, always solved with one variant of these two approches:

  • Use a database trigger, that fires with every change in the entities you need to track.
  • Manage it programmatically, a painful solution that contaminates your code.

Hibernate Envers to the rescue

The Envers project “aims to enable easy auditing of persistent classes. All that you have to do is annotate your persistent class or some of its properties, that you want to keep track of, with @Audited. For each audited entity, a table will be created, which will hold the history of changes made to the entity”.

The Envers project is now a Hibernate core module (since 3.5+), so it is really easy to include it in your projects. As promised, you only need to annotate your entities:

@Entity
@Audited
public class MyEntity {
   ...
}

Add the following properties to your persistence.xml, to configure the listeners that need to be called when a persistence related event is fired:

<property name="hibernate.ejb.event.post-insert" value="org.hibernate.ejb.event.EJB3PostInsertEventListener,org.hibernate.envers.event.AuditEventListener" />
<property name="hibernate.ejb.event.post-update" value="org.hibernate.ejb.event.EJB3PostUpdateEventListener,org.hibernate.envers.event.AuditEventListener" />
<property name="hibernate.ejb.event.post-delete" value="org.hibernate.ejb.event.EJB3PostDeleteEventListener,org.hibernate.envers.event.AuditEventListener" />
<property name="hibernate.ejb.event.pre-collection-update" value="org.hibernate.envers.event.AuditEventListener" />
<property name="hibernate.ejb.event.pre-collection-remove" value="org.hibernate.envers.event.AuditEventListener" />
<property name="hibernate.ejb.event.post-collection-recreate" value="org.hibernate.envers.event.AuditEventListener" />

And last, if you are using Maven, include it as a dependency in your pom.xml (the dependency scope is “provided” if you use JBoss AS 7.0.2):

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-envers</artifactId>
    <version>${envers.version}</version> <-- i.e. 3.6.8.Final -->
</dependency>

That is all. Every change in an entity will be audited in an automatically generated “player_aud” table. This is the simplest and, most important, cleanest way I currently know to solve the aforementioned problem.

The official docs include other features such as logging, querying historical data, advanced configuration and some unsupported features (bags).

Any critics?

Hibernate Envers is so simple that the only improvement I can think about is to see it standardized as part of the next version of JPA, and to include a single configuration property covering 90% of the cases (or even better, discover if the entities are marked as auditable at runtime):

<property name="hibernate.auditable" value="true" />

Any comment is welcome.

UPDATE: With Hibernate 4.x it is no longer necessary to add the event listeners to your Hibernate configuration. All you need is to put hibernate-envers on your classpath and annotate your entities.

No Comments

Graph your Twitter network with Gephi

by guido on 21/01/2012

Gephi is a really cool open-source (GPL) project for visualizing and analyzing network graphs.

Getting started

If you want to start using Gephi you have two choices:

  • The blue pill, a simple GUI, pretty easy to use, that offers many network metrics, statistical algorithms (clustering, etc) to analyze your own graphs. The story ends.
  • The red pill, the Gephi Toolkit. The toolkit is a standard Java library that can be integrated with your own code if you need to analyze graphs. That is what we need.

Both of them are really modular, and can also be extended with big variety of available plugins, contributed by third party developers.

Crawling your Twitter network

Twitter offers a REST API. In this case I have used Spring Social, an extension of the Spring Framework that simplifies the connection with social networks such as Linkedin, Facebook or Twitter (docs).

For example, obtaining the list of followers of a given user is something as simple as:

TwitterTemplate twitter = new TwitterTemplate();
List<TwitterProfile> result =
        twitter.friendOperations().getFollowers("palmerabollo");

The bad news is that the API is rate limited to 150 requests/hour, and you can increase it if you use OAuth to authenticate your requests. This limit is too low (I think Twitter is trying to protect their data from being extracted) and forced me to introduce a basic cache layer (just a Map) to save some requests. The cache is coupled with the application code, it could be certainly improved.

Final result

You can find the code at github. Remember that this is a proof of concept, so it can be improved a lot. I am waiting for your pull requests.

Lessons learned and future work

  • Twitter API is very restrictive. A cache tries to solve this problem but it is still not possible to retrieve the deepest levels of your network. It would be fun to use a NOSQL graph database such as neo4j, that even has a Gephi plugin available, to store the data. This question I asked in the Gephi Forum is a good starting point if you are interested on it.
  • Gephi Toolkit and its plugins are not available from a Maven repository, so I included them as system libraries in my pom.xml. This is the first time I do it, and it is probably a bad practice. I would like to hear your opinion about this.
  • Gephi is a really interesting and powerful project, but the documentation and examples could be improved.
  • It would be very interesting to play with other Gephi advanced features such as filtering, clustering. For example, to detect “communities” or to detect the most influential nodes in your network.
  • Spring Social simplifies your life, offering a common interface to work with different social networks, saving you the pain and hassle of dealing with every different API out there.

By the way, if anyone else is interested in offering this service through a web interface, please let me know.

No Comments

ACRA, reporting crashes in your Android app the easy way

by guido on 20/12/2011

ACRA (Application Crash Report for Android) is a extremely helpful Android library that allows your mobile application to send a report to different destinations when it crashes -miserably-.

It is both powerful/configurable and very easy to use at the same time, allowing:

  • Different kind of notifications (silent, toast, status bar, etc)
  • Detailed crash reports (stack traces, device model, system versions)
  • Many targets (email, shared google spreadsheet, etc)

In my example I have used a shared google document as the target where the notifications are sent, and I have chosen not to show anything to de user when the application crashes (silent mode).

Once you download and add the acra-x.x.x.jar file to your project, you simply need to annotate your Application class:

import org.acra.ACRA;
import org.acra.ReportingInteractionMode;
import org.acra.annotation.ReportsCrashes;
import android.app.Application;

@ReportsCrashes(
		formKey = "<my_google_doc_key>",
		mode=ReportingInteractionMode.SILENT)
public class MyApplication extends Application {
	@Override
	public void onCreate() {
		super.onCreate();
		ACRA.init(this);
	}
}

It is important to add the permissions required to use the Internet connection in your AndroidManifest:

<uses-permission android:name="android.permission.INTERNET" />

A crash report

Once your application crashes (it will crash), you receive a lot of useful information such as the device status:


locale=es_ES
hardKeyboardHidden=HARDKEYBOARDHIDDEN_YES
keyboard=KEYBOARD_NOKEYS
keyboardHidden=KEYBOARDHIDDEN_NO
fontScale=1.0
mcc=214
mnc=7
navigation=NAVIGATION_TRACKBALL
navigationHidden=NAVIGATIONHIDDEN_NO
orientation=ORIENTATION_PORTRAIT
screenLayout=SCREENLAYOUT_SIZE_NORMAL+SCREENLAYOUT_LONG_YES
seq=5
touchscreen=TOUCHSCREEN_FINGER
uiMode=UI_MODE_TYPE_NORMAL+UI_MODE_NIGHT_NO
userSetLocale=false

width=480
height=800
pixelFormat=1
refreshRate=60.0fps
metrics.density=x1.5
metrics.scaledDensity=x1.5
metrics.widthPixels=480
metrics.heightPixels=800
metrics.xdpi=254.0
metrics.ydpi=254.0

And the stacktrace, in a transparent way for the user:


java.lang.NullPointerException
at java.util.Collections.sort(Collections.java:1971)
at net.guidogarcia.SelectActivity$a$1.run(SourceFile:197)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:144)
at android.app.ActivityThread.main(ActivityThread.java:4937)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(...)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)

In my case the output seems pretty cryptic because I was also trying to integrate Proguard in the application.

Open points

I am far from being an Android expert, so I would like to know if there is another way to submit this kind of reports that does not need an external library (please use the comments if you know how to do it).

The version I have used is ACRA 3.1.1, so this article might be outdated with the release of ACRA 4.x.

No Comments

Getting started with Spring Roo

by guido on 5/12/2011

For those who are not familiar with it, Spring Roo is an open source tool that provides rapid application development of Java applications, using standard Java technologies underneath.

Last week I gave a presentation (slides) about how to start using Spring Roo to some co-workers in Telefónica Digital. I have recorded a video with captions for those who couldn’t attend (use fullscreen mode and 720p).



The video does not cover some interesting aspects about Spring such as Spring Data (I will write a post about it), or how to completely remove Spring Roo from your project (right button > Refactor > Push In and that is all).

If you are planning to give it a try, I strongly recommend to use Spring Roo 1.2.x in order to create layered architectures (controller + service + repository), instead of using the Active Record pattern (in words of Martin Fowler, “An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data”)

When would I use Spring Roo

Spring Roo is a relativly young project (Q4 2009), it is evolving really fast, and I think it is especially useful:

  • To create your Spring project structure. Roo generates a typical Maven + Spring project. I think it is a good idea to use a proven structure and keep it consistent in every new project you start. Remember that you can remove Roo at any time, so you are not tied to it.
  • To develop domain-intensive applications, that fit well with a CRUD user interface. Even administrative web interfaces to your existing applications seem good candidates to be developed with the help of Spring Roo.

Comments are open. Where are now the Ruby on Rails guys?

No Comments

Scripting for the Java platform

by guido on 3/11/2011

Despite many developers do not know it, since Java SE 6 it is really easy to integrate Java and some scripting languages through a standard Java Scripting API (JSR-223 implementation)

Currently, both AppleScript (2.2.1) and ECMAScript (1.6) script engines are supported by default, at least on my machine. In the following example I invoke a Javascript function from Java, using Mozilla Rhino, the JavaScript implementation that ships with Java SE 6:

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

public class TestScript {
  public static void main(String[] args) throws Exception {
    ScriptEngineManager mgr = new ScriptEngineManager();
    ScriptEngine engine = mgr.getEngineByName("js");

    String script = "function sum(a, b) {" +
                    "   var result = a + b;" +
                    "   return result;" +
                    "}";
    engine.eval(script);

    Invocable invocableEngine = (Invocable) engine;
    Number result =
            (Number) invocableEngine.invokeFunction("sum", 2, 3);
    System.out.println(result); // output = 5.0
  }
}

Reuse existing code

I find this “trick” useful in cases where you want to reuse existing scripting code. In the following example I use the great datejs library to parse dates written in natural language:

import java.io.InputStreamReader;
import java.io.Reader;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class DateParser {
    private final ScriptEngine engine;

    public DateParser() throws ScriptException {
        ScriptEngineManager mgr = new ScriptEngineManager();
        engine = mgr.getEngineByName("js");

        Reader reader = new InputStreamReader(
                this.getClass().getResourceAsStream("/scripts/date.js"));
        engine.eval(reader);
        engine.eval(
        	"function parse(value) { " +
        	"    return Date.parse(value).toDateString();" +
        	"};"
        );
    }

    public String parse(String naturalLanguageDate)
            throws ScriptException, NoSuchMethodException {
        Invocable invocableEngine = (Invocable) engine;
        return (String) invocableEngine.invokeFunction("parse", naturalLanguageDate);
    }

    public static void main(String[] args) throws Exception {
        DateParser parser = new DateParser();

        // output = Thu Nov 03 2011
        System.out.println(parser.parse("next thursday")); 

        // output  = Wed Nov 09 2011
        System.out.println(parser.parse("tomorrow + 10 days"));
    }
}

Well, that is all for the proof of concept I was looking for. If you want to read a more complete and deep article about this subject, I recommend Java Scripting Programmer’s Guide at Oracle.

Problems found

So far, the most problematic point I have found is the conversion from the Object returned by invokeFunction to the appropriate Java types. It is not hard when it is a simple type such as a Number or a String, but it is not so easy when it comes to a more complex type (Array, Date). This is why the parse function in the second example returns a String instead of a Date.

In my first attempt I tried to create a neural network with brain, a javascript supervised machine learning library. It would have been an interesting and even useful piece of code, but I failed miserably, probably because they use code not supported by ECMAScript 1.6.

A little benchmark would also be great, to determine the overhead introduced (if any) when you execute scripting code from Java, and compare it with a external/standalone script engine.

No Comments

Java : different ways to filter a Collection

by guido on 29/10/2011

Imagine we have a simple Java class:

  public class Person {
    private int age;
    private Gender sex;

    // constructor, getters & setters
  }

  enum Gender { MALE, FEMALE };

And that you have a Collection of Person objects, such as the following one:

  Person p1 = new Person(35, Gender.MALE);
  Person p2 = new Person(30, Gender.MALE);
  Person p3 = new Person(25, Gender.FEMALE);
  Person p4 = new Person(15, Gender.FEMALE);		

  List<Person> people = Arrays.asList(p1,p2,p3,p4);

How would you create a new Collection containing only men over 21?

Use plain Java, like real men do

  List<Person> result = new ArrayList<Person>();
  for (Person person : people) {
    if (person.getAge() > 21 && person.getGender() == Gender.MALE) {
      result.add(person);
    }
  }

  // now result contains the filtered collection

Filtering by predicate

The second option is what Commons Collections and Guava propose, and that I think should have been part of the Java core at least since Java 5.

  public interface Predicate<T> { boolean apply(T type); }

  public static <T> Collection<T> filter(Collection<T> col, Predicate<T> predicate) {
    Collection<T> result = new ArrayList<T>();
    for (T element: col) {
      if (predicate.apply(element)) {
        result.add(element);
      }
    }
    return result;
  }

It remembers me the visitor pattern. With this approach in mind, you can define a set of predicates:

  Predicate<Person> validPersonPredicate = new Predicate<Person>() {
    public boolean apply(Person person) {
      return person.getAge() > 21 && person.getGender() == Gender.MALE;
    }
  };

  Collection<Person> result = filter(people, validPersonPredicate);

I find it very similar to Python’s filter() function, but more verbose due to Java’s nature.

This way your code becomes cleaner, and you can combine fine-grained reusable predicates. As a future line of work, it would be interesting to define a fluent interface that allows chaining of several predicates in a more natural way.

JSR 335, Project Lambda and lambdaj

JSR 335 (Lambda Expressions for the Java Programming Language) is part of JSR 337 (Java SE 8), which is scheduled for release in late 2012.

Lambda syntax is already decided (it is similar to C# and Scala) and what I hope is to see something similar to this kind of filtering, method chaining included:

Collection<Person> result = people
    .filter(p => { return p.age > 21 })
    .filter(p => { return p.gender == Gender.MALE });

If you can not wait and need to start using that kind of syntax today, I recommend the lambdaj library, it is not the same but it is handy in some cases:

Collection<Person> result = with(people).clone()
    .retain(having(on(Person.class).getAge(), greaterThan(21)))
    .retain(having(on(Person.class).getGender(), equals(Gender.MALE)));

I have not tried the last snippet but you get the idea. Notice you have to call clone() if you want to leave the original collection unchanged.

A small benchmark

As a second line of work, a comparison between the three alternatives is still to be done. I suppose the use of predicates is cleaner at the cost of a lower performance.

Comments are open.

1 Comment

My first Javascript robotics simulator (and II)

by guido on 18/09/2011

A week ago I wrote a post about a Javascript robotics simulator. As an experimental project, I took the opportunity to try different technologies: HTML5, Javascript and Git. In this post I am going to write about what I have learnt with this project from a technical point of view, and what the future lines of work could be.

HTML5

I learnt how the new slider input works, and how to use a canvas to display graphical information into a web browser. The canvas element is not intended to keep track of a set of moving objects because it only knows about pixels (read more about this). For this reason SVG could have been a good alternative in this case.

I also tried to use Web Workers to run the simulation in the background, avoiding to block the UI, but I had some problems sending information back and forth to the workers, so this feature will have to wait (the code is shared at github, so contributions are welcome)

HTML5 support is already pretty good and, if in one of my last posts I blamed Google, today I have to say they are making a great effort to take the Internet forward.

Javascript & TDD

I mostly work with Java, so my mind tend to think in an object-oriented way. I tried to discover good practices about how to organize the code, but I must admit I still have to learn a lot about Javascript. The fact that my code is a port from C# did not help at all. To compensate for it, I had the chance to install and try MonoDevelop.

I also tried to learn how to adopt TDD practices in Javascript. I finally did a proof of concept with the console object. This is an example:

// Code to be tested
function Vector2(x, y) {
    this.x = x;
    this.y = y;

    this.plus = function(vector) {
        return new Vector2(x + vector.x, y + vector.y);
    };
}

// Tests
console.group("Coordenates are set");
    v = new Vector2(3, 2);
    console.assert(v.x === 3, "x coordinate is not set");
    console.assert(v.y === 2, "y coordinate is not set");
console.groupEnd();

console.group("Sum two vectors");
    v1 = new Vector2(3, 2);
    v2 = new Vector2(5, 7);
    res = v2.plus(v1);
    console.assert(res.x === 5 + 3, "added x coordinate is wrong");
    console.assert(res.y === 7 + 2, "added y coordinate is wrong");
console.groupEnd();

It is probably the easiest way to write a unit test in Javascript, but it is very limited as well. The second point to be done is to try a complete testing framework such as QUnit or Jasmine, as recommended by Alejandro.

GIT. Sourceforge who?

I shared the code in github (please feel free to contribute) and I tried the new EGit plugin to work with github (or any other git repository) from Eclipse.

It works fine, but despite I can see many of the advantages of git, I don’t think it is easier or more intuitive to use than SVN. I am still not used to the whole git workflow, but I will keep trying because what is clear is that github is amazing and has changed the way people cooperate in the open-source world.

Other lines of work

  • Fix existing bugs when obstacles are present.
  • Compare the ORCA algorithm with other ones, specially those related with genetic algorithms. Apply this kind of algorithms to model human behaviour, more effective placement of emergency exits in buildings, etc.
  • Integrate this algorithm into a piece of hardware, such as an Arduino board. I can also think about several Roomba robots sweeping my floor in less time without collisions.
1 Comment

My first Javascript robotics simulator (I)

by guido on 13/09/2011

I must admit I have always been fascinated about robotics, especially about how a swarm of robots can cooperate, following a set of simple rules that lead to complex emergent behaviours, like those you can see in the exciting motion of a flock of birds.

Whereas I have some elctronics background, the bad news is that I am a software developer at heart. This is why I find a big obstacle when it comes to the hardware layer. My last experiment in this area is a software multi-agent simulator, where multiple independent agents avoid collisions with each other without communication among them while moving in a common arena.

It seems like a hard task, but it is only an experimental port from the C# version of the already existing RVO2 Library (based on the ORCA algorithm) to Javascript. The whole code is shared in github along with a README file containing basic usage instructions. I am not really proud of the current code, mostly because of my lack of extensive and in-depth experience with Javascript. Please feel free to contribute to improve the project.

As an experimental project, it is not intended to be the most efficient solution. Instead, I took the opportunity to try different technologies: HTML5, Javascript & TDD and Git. In the next post I will write about what I have learnt with this project from this technical point of view, and about the future lines of work.

One demo is worth than one thousand words

I have set up a couple of demos (radial demo, linear demo) where you can adjust some parameters (number of agents, agent size, presence of obstacles) and run a simulation. Remember that you need a modern browser with HTML5 support (i.e. Chrome or Safari) and, depending on the number of agents, a decent CPU if you want to smoothly run it.

RVO2 simulator

What I find most interesting here is that the agents are completely autonomous, a kind of “collective intelligence” emerges, but the agents do not communicate any information among them to coordinate their movements. You should be impressed at this point. Please use the comments sections if you have any idea or any suggestion to improve the simulator.

Real life applications

I can imagine using this algorithm for several applications, all of them are already very well documented in the Internet:

  • Robotics. Coordinate robots in a factory to avoid collisions (example).
  • Games development. See RVO2 Library integration with Unreal Development Kit. If this rvo2-js library evolves it could be used in javascript games.
  • Human behaviour. Model human behaviour in crowded supermarkets, shopping malls and sports stadiums, or even during emergency situations.

I am sure there are many other applications you can think about. Use the comments below to share your feedback and questions.

No Comments