Disqualifications & Coverage

I am glad to see that there is an extensive article about the double disqualification of Amiel Tenenbaum and his opponent in Wizards’s coverage of Worlds 2006. I just had the discussion with another judge on #mtgjudge, whether this should be covered and how extensive.

I think covering DQs has several advantages:

  • It generates interest in the game. People like gossip. I know I do. Personally I couldn’t care less about play-by-play coverage, but I’m interested in stuff that happens at these events. I want stories. I want gossip. I want photos.
  • There is a professional interest for me as judge. It shows me how people cheat or try to cheat. It shows things than can happen that lead to disqualifications.
  • It shows that judges catch cheaters. If you read Magic-related message boards (and manage to keep your sanity) you will notice that many players, especially more casual ones, believe that cheating is rampant and cheaters are never caught. Making disqualifications public can help to dispell this myth. It shows that the tournament organizing staff will catch cheaters and that they will be penalized.
  • Word gets around if a player is disqualified. Whether it’s in the official coverage or not. It’s better to have an informed article with interviews with judges involved or the even the players. Otherwise people will speculate and lots of false rumors are started.

On the other hand the coverage still hasn’t got enough photos. And I would still prefer a blog from a coverage reporter to the “Pro Players Blog”, which is just another form of (boring) play-by-play coverage.

Gaia shut down by Google

Clint: Did you actually read the letter sent by Google? I actually consider this to be a perfect example of “don’t be evil.” There are no threats in that letter, Michael Jones, the writer, is just explaining why Gaia hurts Google and in what way he think the Gaia project is violating Google’s Terms of Service. He tells the Gaia project members that he understands their curiosity, even calls them “smart engineer[s] like ourselves”, but asks them to “refocus [their] work toward building an open earth viewer that uses open earth images.”

I don’t think that Google is free to do whatever they want with the images of the earth stored on their server. They most likely have a rather restrictive deal with the actual image providers. And even if they hadn’t, Google probably pays a rather large amount of money to these image providers. I can understand that they don’t want to offer these images for everybody to grab.

I consider this letter to be very kind and understanding, compared to what seems to be standard today: Let the lawyers do the talking, or don’t bothering with the talking at all and just sueing.

Java: Iterators are not Iterable

This is something I stumbled across multiple times now in Java: Iterators are not Iterable. Java 1.5 introduced the foreach statement, which allows easy iteration over collections like this:

for (MyClass item: myCollection) {
    doStuffWithItem(item);
}

For this to work class MyClass must implement the Iterable interface. This interface defines just one method that returns an Iterator:

    Iterator<T> iterator();

This works fine in many cases. But now suppose we have a class that can be iterated in multiple ways. For example a Tree class that can be iterated breadth first or depth first. I would define two methods and use them like this:

class Tree {
    Iterator<Node> depthFirstIterator();
    Iterator<Node> breadthFirstIterator();
}

// ...
    for (Node node: myTree.depthFirstIterator()) {
    }

This won’t work in Java. Iterators do not extend the Iterable interface, like they in other languages. For example in Python an iterator will return itself when its iterator() equivalent is called. Instead in Java I have to return an object that itself implements the Iterable interface like this:

class IterableIterator<T> implements Iterable<T> {
    private Iterator<T> iter;

    public IterableIterator(Iterator<T> iter) {
        this.iter = iter;
    }

    public Iterator<T> iterator() {
        return iter;
    }
}

class Tree {
    IterableIterator<Node> depthFirstIterator();
    IterableIterator<Node> breadthFirstIterator();
}

Not only is this boilerplate code for no gain, a generic class like the IterableIterator above is not included in Java’s standard library.

JavaScript Includes Revisited

I’ve given in in the JavaScript and Modules matter. I’m doing now what all the cool kids are doing: Using XMLHttpRequest synchronously to load external JavaScript files. This has the advantage that it works synchronously, a very important thing for includes. Therefore I don’t need callback and moduleLoadedhackery anymore. Also I have sensible error checking, i.e. I can notice when loading a JavaScript module failed. This enables me to have multiple search paths, for example, and sensible error handling.

But it comes at a cost, too. XMLHttpRequest is only supported by “modern browsers”. But since moderns browsers means any browser of the last five years I don’t care too much. When XMLHttpRequest is not supported, I suppose I can’t rely on other useful stuff neither. The synchronous requests also mean that there might be a slight performance hit. But the advantages of synchronous includes outweigh this by far. Finally, XMLHttpRequest doesn’t provide the means to recognize when a synchronous request is stalled. This is not of too much concern, since a stalled request usually means that an include files can’t be downloaded and so the JavaScript application is not usable anyways. It might be a concern for sensibly degrading, though.

Update: Here is the code to the updated module. Using it is now as simple as this:

<script src="include-http.js"></script>
<script>
    include.include("my.module");
    myfunc(...);
</script>

Porting JavaScript to Internet Explorer

While porting a small AJAX application I wrote to Internet Explorer, I encountered a few problems:

  1. IE doesn’t like <script> tags without a matching closing tag. This is especially a problem if you use the src attribute and try to use an XHTML-like closing tag like this:
    <script src="..."/>
    

    In this case IE doesn’t draw anything at all, since it keeps looking for the end of the script and doesn’t find it. This is especially a problem with templating toolskits like Kid. If Kid encounters a construct like <foo></foo> it will correctly shrink this to <foo/> in the XML output. The solution is rather easy: Insert a newline character between openening and closing tag in the template. Since Kid has now way to determine whether this whitespace is significant it will keep it in the output.

  2. It seems that IE doesn’t like trailing commas in JavaScript object literals:
    var o = {
        x: 'Foo',
        y: 1,
    };
    

    I like to insert trailing commas in cases like this. It’s easy to forget to add one if extending the property list. Firefox parses the trailing comma, while IE doesn’t. (IE follows the ECMAScript standard here, which doesn’t allow the trailing comma. Indeed in array literals a trailing comma has a special meaning, so it’s probably a good idea to disallow the trailing comma in object literals.)

  3. My AJAX application queries a web service for a list of items and displays that list in a table. The table is generated in HTML code like this:
    <table id="mytable">
        <tr>...</tr>
    </table>
    

    I then used JavaScript code like the following to populate that table:

    var table = document.getElementById("mytable");
    var trTag = createRow();
    table.appendChild(trTag);
    

    This worked fine in Firefox, but no matter what I did, IE refused to render the table rows. After much hair tearing I remembered that Firefox’s DOM Inspector showed a TBODY element just beneath the TABLE element and TR elements are attached to the former. The DOM Inspector basically showed the following structure:

    • TABLE id=mytable
      • TBODY
        • TR (my header row from the HTML)
      • TR (a dynamically generated row)

    So I changed my code to append the newly generated rows to the TBODY instead:

    var table = document.getElementById("mytable").
        getElementsByTagName("tbody")[0];
    var trTag = createRow();
    table.appendChild(trTag);
    

    This works in Firefox and IE.

Apache, cgi-bins, and the Authorization header

I had a problem: Server A runs a web service, which requires users to authenticate using the standard HTTP authentication mechanism. Server B should have web pages that use AJAX to query A’s web services. Server B’s web pages also require authentication, using the same scheme, backend and database as server A. There are two problems:

  1. JavaScript web pages can only access web services/pages on the same server using XMLHttpRequest, for security reasons. Solution: Use a forwarding/proxy service. E.g. to access http://a.example.com/service from b.example.com add a service http://b.example.com/servicethat just forwards requests to the web service on A. This solution is quite straight forward.
  2. Since B uses the same authentication scheme as A we need to forward authentication information passed to B’s forwarding service on to A. Unfortunately this is not straight-forward, since the Apache HTTP Server provides no easy way to read the full authentication information passed to it via a cgi-bin. The only available information is the REMOTE_USER environment variable. This is not enough to construct a new Authenticationheader, though, since password information is stored encrypted in the account database.Finally I found a solution in the Zope 2 documentation. Apache’s mod_rewrite comes to the rescue. It allows you to read arbitrary HTTP headers and add arbitrary environment variables before executing a cgi-bin. The following recipe added to the appropriate .htaccess file adds a HTTP_AUTHORIZATION variable:
    RewriteEngine on
    RewriteBase /
    RewriteCond %{HTTP:Authorization}  ^(.*)
    RewriteRule ^(.*)$ $1 [e=HTTP_AUTHORIZATION:%1] 
    

Loading Modules in JavaScript

One of the weaknesses of the JavaScript language is that it does not have the concept of “importing” or “including” other source files or modules. In client-side JavaScript as used in web browsers you have to include all JavaScript files you intend to use in the main HTML file like this:

<html>
    <head>
        <title>...</title>
        <script src="A.js"></script>
        <script src="B.js"></script>
        <script src="S.js"></script>
    </head>
    ...
</body>

In this case S.js is a page-specific JavaScript script that uses features from A.js and B.js.

The standard way to load other JavaScript files dynamically is to add a script element programmatically to the head section of the document, using DOM:

function include(filename) {
    var scriptTag = document.createElement("script");
    scriptTag.setAttribute("lang"), "javascript"));
    scriptTag.setAttribute("type"), "application/javascript"));
    scriptTag.setAttribute("src", filename);
    document.getElementsByTagName("head")[0].appendChild(scriptTag);
}

Unfortunately this approach has some problems as well: The include file is loaded “lazily”, i.e. the next time the JavaScript interpreter hands back control to the browser. (At least it is this way in Firefox.) If, for example, a file A.js defines a function func_a, the following will not work:

include("A.js");
func_a();

My first solution was to use a callback, invoked when the module has been loaded:

function include(filename, callback) {
    var scriptTag = createScriptTag(filename); // as above
    scriptTag.onreadystatechange = function() {
        if (scriptTag.readyState == "complete") {
            callback();
        }
    }
    scriptTag.onload = function() {
        callback(file);
    }
}

This solution uses the non-standard onload (Firefox) or onreadstatechange (IE) events. It is invoked like this:

include("A.js", function() {
    a_func();
});

This solution also has several problems: It is non-standard, it is ugly (though this can’t be helped, due to the asynchronous script loading), and including a module from a module still doesn’t work. To explain the last problem, I will use a script S.js which depends on the function a_func defined in A.js, which in turn depends on b_func defined in B.js. Now the code should look like this:

// S.js
include("A.js", function() {
    a_func();
});

// A.js
include("B.js", function() {
    a_func = function() {
    }
    a_func.prototype = new b_func();
});

// B.js
// ...

The problem is that the callback in S.js is not necessarily processed after the callback in A.js, leading to a_func being undefined.

The solution I have come up with is not particularily nice, but this can’t really be helped. Basically each module has to call a function when it has fully loaded, like this:

// A.js

include.module("B.js", function() {
    // ...

    include.moduleLoaded("A");
});

The main HTML file must load the include.js before loading any other module and modules should only be loaded via include.module. Also my implementation uses “real” module names, e.g. a.b.c instead of a/b/c.js. This allows me to expand the mechanism easily, for example to add a module search path.

Sample implementation

PTQ Geneva in Berlin

Yesterday the Pro Tour Qualifier Geneva in Berlin was held at FUNtainment. We had 110 players, a rather high turnout, among them many players from Poland. It’s always nice to have these guys around. One thing I noted, though, was that I stepped in multiple times when a player and a spectator were speaking in Polish. When players and spectators do that in German I often don’t step in, since I hear what they say and most of the time it’s not about the game. So I subconsciously filter that talk out. I can’t do that for a language that I don’t understand, though.

Helping me were acting TO Peter, Christoph (L1), and Kersten, my promising judgeling. While we were understaffed by one person for this event (but aren’t we always?) the event went rather smooth. The main problem was that we couldn’t do as much deck checks as I would have liked to and that sometimes we couldn’t cover all the matches in overtime. One more judge would have been quite beneficial in these cases, but as I have explained before, we don’t have that many active judges anymore and a few possible candidates chose to play instead of judging.

Also of note was the high number of appeals I got. During the first two rounds I had three appeals, while I usually get about one per tournament. But this became less during later rounds.

About a quarter of an hour before the tournament began we had a call in the store. A rather young boy asked whether it was possible to participate in the event where “you can qualify for the Pro Tour”. I told him to hurry up, since we wanted to start soon. He showed up a bit too late with his mother, but I still let him participate. This was obviously his first sealed deck tournament, and I absolutely forgot to mention that the cards were in English. I would have liked to have more time to talk to him before the event to explain everything, but unfortunately didn’t have the time in the stress at tournament start. Well, he build an 80 card deck, playing all the basic lands from the tournament pack, although I had explained to him that he can get more lands if he wanted to. Not very surprisingly he went 0-4 drop. I am kind of sorry for him, and wish I could have found more time for him.

In the last round I handed back the decks from a deck check seven minutes into the round. The players from a neighbouring table asked me: “Can we get extra time? We didn’t start playing yet, since we couldn’t decide whether to take an intentional draw.” I explained to them the errors of their ways.

PyUnit and Decorators

One of the shortcomings of the Python standard library is in my opinion that PyUnit doesn’t use decorators (as later versions of JUnit and NUnit do). Therefore I have written a sample implementation that adds decorator support. (unittest.pydiff to Python 2.5’s unittest.py)

To do:

  • Warn when old-style and new-style tests are mixed.
  • Throw an exception when multiple setup or teardown methods exist.
  • Ability to warn when old-style methods are used.