Archive for the ‘Web’ Category

Unicode Mirror Character

Wednesday, August 4th, 2010

It turns out that unicode standard defines a character that explicitly reverses the following text. You can insert it as ‮ in your html. Here is a sample:

Normal Text:

Send more money

Prepended By Mirror Character:

‮Send more money

Here is the specification of algorithm.

Writing Gadget for Google Wave

Sunday, November 15th, 2009

Recently I got a Google Wave account and could not help myself to play with it. The most interesting feature for me is the shared state associated with every wave. This allows to embed multi-user widgets into the wave (in Google terminology gadgets inside wavelet). All other widgets I know are designed for a single user; for example Mac OS X dashboard widgets are written using the same web technologies and even have access to some system functionality but essentially they are just the tiny web pages. Google wave gadgets are designed with many concurrent users in mind and this makes them really the tiny web applications.

So I decided to write a gadget that is good for several people, and the best candidate seems to be a simple game. Five in a row was a perfect candidate since it requires only and images. It also has a fixed 15 by 15 board and simple win condition.

Google provides a brief but comprehensive guide on the topic of writing gadgets and this is the first thing that you should read. From the developer perspective gadget is composed like this:

  • XML wrapper that describes the gadget and lists its dependencies, name, height and other properties
  • HTML elements that comprise the gadget UI; you will need at least one div that you will use as an anchor to build dynamic UI upon
  • JavaScript code to handle user input and state updates

Physically gadget is an XML file with a Content element that wraps all HTML and JavaScript in CDATA section. This is not convenient because syntax highlighter and other features of dedicated HTML and JavaScript editors do not work for embedded content. I would prefer to have several files with html and js extensions that could be referenced from the XML file. This way it would be easier to create widgets that target several environments. Now if I would decide to make this game available as a Mac OS X dashboard widget I have to create a separate JavaScript file and duplicate the game logic.

There is also one difficult place in the API: concurrent modification of the shared state. The documentation is very succinct on the point:

Not only is a Wave gadget's state shared among all Wave participants, but in the typical case, any participant can change the gadget's state at any time. If two users change values for different keys at the same time, the wave resolves it. However, if the value for the same key is changed, only one change goes through.

What if two users start the game at the same time? After user clicks on the New Game button I send delta with several properties. All property names are the same in two deltas and I think one of the deltas will be just discarded, but if there would be unique property names the state would be corrupted. What is still not clear for me is how they determine when to discard the second delta. I assume they discard it if it comes before all participants are notified about the first delta but it would be helpful to know for sure.

The game logic is simple and I will not put it here except one caveat: full state restore. When game state changes wave sends you an update by invoking a callback function that you register during initialization. During normal gameplay I process only the last move for efficiency but when user switches from another wave the field is clear and I have to perform the full state restore.

  function stateUpdated() {
    var state = wave.getState();
    var move = state.get('move');
    if (!window.g_xoStateFullyRestored) {
      fullStateRestore();
      window.g_xoStateFullyRestored = 1;
    } else {
      if (move) {
        var col = state.get('col' + move);
        var row = state.get('row' + move);
        var cell = cellAt(col, row);
        if (move % 2) {
          makeXCell(cell);
        } else {
          makeOCell(cell);
        }
      } else {
        var board = document.getElementById('board');
        var cells = board.getElementsByTagName('div');
        for (var i = 0; i < cells.length; i++) {
          clearCell(cells.item(i));
        }
      }
    }
  }

I have also designed the game logic in a way that allows users to play both sides at the same time. The same user can start a game and join it but if it is played by two distinct users then of course each user can do moves only of its side.

xo5.png

You can also check this game in the Google wave samples gallery.

Overall I like the platform and would be interested in its success. I have not tried all the features yet but hope to find some time for it. I think the next thing I would try to do is to write a robot that can play this game.

Oh, and here is link to the gadget if you would like to give it a try: http://dizbits.googlecode.com/svn/trunk/xo5/xo5.xml

Classes for JavaScript

Thursday, October 29th, 2009

Classic OOP relies on classes that are essentially object blueprints. You define a class by naming it and adding attributes and methods. Objects are created by new operator that allocates memory and initializes it accordingly to the class design. The ultimate purpose of this setup is to create objects that can do appropriate things.

Each object encapsulates data in its attributes, typically hiding them from other objects. Methods defined in class are bound to objects and are used to give access to object data, for reading or writing. This turns object into an abstraction with a particular interface; you think of objects as of entities that can do certain things and don't care how they do it. This is the reason why OOP is so popular: it is a natural implementation of the 'divide and conquer' principle; instead of shuffling primitive numbers and strings you wire more complex entities to communicate and solve your computing problems.

In JavaScript we have objects but no classes. Actually there are some classes, but they are fixed and you can't define your own class. Every custom object you create is a simple dictionary: a bag of name-value pairs that may store numbers, strings, functions and other objects.

Objects are created by the new operator and initially have no properties or methods (except 'system' stuff like the toString() function). You are supposed to initialize objects later, possibly by providing a dedicated function to do it. And you may write this function in a way that will complement the new operator and make objects look as if they were created from the same blueprint. This means that in JavaScript we may substitute class by a constructor function.

Since every function invocation in JavaScript creates a closure we may use it to store object's hidden attributes. This means that objects in JavaScript are split in two parts: the object itself that exposes the behavior and closure with private stuff.

Below is a Java class and JavaScript function that achieve the same effect:

class Order {
  public String article;
  private double price;
  private int quantity = 1;

  public Order(String article, double price) {
    this.article = article;
    this.price = price;
  }

  public double total() {
    return quantity * price;
  }

  private int validQuantity(int value) {
    return value < 1 ? 1 : value;
   }

  public void setQuantity(int value) {
    quantity = validQuantity(value);
  }
}

function Order(article, price) {
  this.article = article;
  var quantity = 1;

  this.total = function() {
    return quantity * price;
  };

  function validQuantity(value) {
    return value < 1 ? 1 : value;
  }

  this.setQuantity = function(value) {
    quantity = validQuantity(value);
  };
}

Here are the rules to convert Java classes to JavaScript constructor functions:

  1. Identify class constructor and translate it to JavaScript.
  2. Constructor parameters automatically become private attributes.
  3. Declare and initialize local variable for each missing private attribute.
  4. You don't have to declare public attributes, they will be represented by object properties. However, you should initialize them.
  5. Translate public methods to JavaScript functions and bind them to object properties.
  6. Translate private methods to JavaScript functions.
  7. All protected attributes and methods become public.