Introducing Calliope

Recently I felt the need to share more of my “private projects”, so that someone else passing by can read about them and maybe find them interesting. My hope is that by making more things public I can get more motivated to continue on and not let those projects die.

For those reasons, I’m introducing to you my latest project: Calliope.

Calliope is a word game similar to Scrabble, but with a twist. It is played by two or more players, with every player having 7 lettered tiles on a rack; points are scored by placing them on a board to form existing words. The twist that I added to the game is that during your turn you can use all the letters already on the board, that is: you can grab them and move them around at your wish to form new words (I grabbed the idea from a popular – in Italy – card game called Macchiavelli); you however only receive points for the words in which you put at least one of your rack’s letters.

In the same period I “invented” Calliope by merging Scrabble and Macchiavelli I was discovering the existence of new web frameworks and technologies that I would have liked to experiment with. Since at that time I hadn’t a “private project” going on I decided to start one on Calliope itself, and to implement a digital version of the game based on web technologies.

Here is a sneak peak of the result at current stage of development:

Update: more screenshots here!

It is essentially a multiplayer real-time game, in which two or more players can interact with the board in turn. As you can see there’s the rack on the bottom of the page, and there’s a chat on the right with which one can communicate with the other players. Here is how it is constructed:

  • the client side – portraid in the picture – is made on top of Sproutcore, a javascript framework aimed to build desktop-like applications, great stuff;
  • the graphic part (essentially, the board) has been built using Raphael, which gives a nice and smooth javascript interface to SVG programming – I integrated it with Sproutcore myself;
  • the back of the house/server side is built on top of symfony 2, a blazing fast any-purpose php framework.

At the beginning of the project I had no idea of how Sproutcore, Raphael or symfony 2 worked; it has been – and will be – an opportunity for me to learn them. By the way, I also experimented on two other things: RESTful web services (to prepare for the topic I also read this book by Richardson and Ruby) and git, which I never tried before.

At current stage of development, the game is playable but not really stable, and there are still a number of open things to be done. However, I am hoping to put a demo online as soon as possible, to show you more of the project.

This was only an introduction, stay tuned for more! 🙂

Update: this post has become the first of a series of posts about Calliope, you can find the index here.

A better Record::copy()

Today I’m going to bore you with low-level technical stuff so, if you’ve nothing to do with Symfony or Doctrine you are allowed to leave now.

For the rest of you who love this kind of things, here’s the situation: I’m working on a project which was made some months ago using Symfony 1.2 with Propel and by opening it up again to make some big changes I decided to migrate to Symfony 1.4 and Doctrine (which seems to be the preferred choice for Symfony now).

During the transition I found that the copy() method of Doctrine_Record doesn’t behave at all as its Propel counterpart, and is infact quite buggy: it does duplicate child records (which it should) but is does duplicate parent records as well (which it shouldn’t!) and it doesn’t duplicate referenced records if you don’t load them in advance from the database.

To fix this behavior I defined a new class called BaseDoctrineRecord with my own version of copy(), here it is:

  class BaseDoctrineRecord extends sfDoctrineRecord
  {
    /**
     * Fixes the buggy copy method of Doctrine_Record
     *
     * @param bool $deep
     * @return BaseDoctrineRecord
     */
    public function copy($deep = false)
    {
      $ret = parent::copy(false);
      if (!$deep)
        return $ret;

      // ensure to have loaded all references (unlike Doctrine_Record)
      foreach ($this->getTable()->getRelations() as $name => $relation)
      {
        // ignore ONE sides of relationships
        if ($relation->getType() == Doctrine_Relation::MANY)
        {
          if (empty($this->$name))
            $this->loadReference($name);

          // do the deep copy
          foreach ($this->$name as $record)
            $ret->{$name}[] = $record->copy($deep);
        }
      }
    }
    return $ret;
  }

Then it was only matter of changing the base class of doctrine auto-generated models to my new BaseDoctrineRecord, and this can be done by adding the following lines to ProjectConfiguration:

  public function configureDoctrine(Doctrine_Manager $manager)
  {
    $options = array('baseClassName' => 'BaseDoctrineRecord');
    sfConfig::set('doctrine_model_builder_options', $options);
  }

And that’s all, simple as that. For me it’s just working perfectly, feel free to reuse the code in your own project.

Hope this can help someone, byeee.