bookmark_borderCloning ActiveCollab

Just over 3 months ago, the developer of a a nifty little open source project management tool called ActiveCollab decided to go commercial and more or less drop the open source version. This didn’t sound too bad at the time, but as I got thinking I realised that there was a definite lack of simple project management tools which were open source. Most of those I found had clunky interfaces or a questionable development status. And of course, more or less all of them are written in PHP, not my most favourite programming language to say the least.


ActiveCollab Dashboard

In the end, I was left with uncertainty of the future of ActiveCollab, so I decided to hit two bird’s with one stone and fork my own version of ActiveCollab, but this time rewrite it in Ruby using the Ruby on Rails framework with a goal of making it open source. This seemed like a good idea at the time, as:

  1. I didn’t like PHP
  2. I was a bit of a novice at programming in Ruby
  3. My experience of dealing with the Ruby on Rails framework was sketchy to say the least
  4. ActiveCollab’s PHP framework was similar to Ruby on Rails
  5. Open source is great, lots of people will be interested in working on it with me

The development process started as thus:

  1. I started off with a run-of-the-mill started Ruby on Rails framework project
  2. I ported ActiveCollab’s DB Schema over into the schema.rb
  3. Using the PHP code and the schema as reference, i’d make basic Model’s for each type of object used.
  4. I’d decide to implement a controller
  5. Using the original php code as a reference, i’d replicate the controller and its action’s in the Ruby on Rails project
  6. I’d also import the associated templates from ActiveCollab and convert them into .rhtml files, which are essentially the same except they use Ruby as the scripting language instead of PHP
  7. Whilst trying to replicate the functionality of the controller, i’d also tweak up the related Model to fill in the gaps of missing functionality
  8. In addition, when I encountered anything missing from the Ruby on Rails framework that was required, i’d find a relevant ‘plugin’ and import it into the project, or just implement it all by myself
  9. I repeated steps 4-8 until I the majority of the functionality was implemented

At first, it started out as a little pet project as mine. Though after a while, I grew a bit tired of developing it (developing in this way became very tedious and boring), and decided to push on with the open source aspect of the project and ask the ActiveCollab community if they were interested in my code. The answer I got back was yes.

And thus I decided to open it up fully to the wonderful world of open source development and placed it on RubyForge. I also decided to give it a cool name, RailsCollab.

Initially when I placed it on RubyForge I was contacted by someone who was interested in assisting. So naturally, I added them to the project. I also added another person, purported to be a friend of theirs that was also interested.

Sadly though a month down the line, I received no signs of life from either of them. It’s as if they thought “wow great, an open source project. lets join in!” and then promptly died from the excitement. Or maybe they just couldn’t be bothered, I don’t know.

So in the end being the kind person I am, I essentially did all the work myself out of the sheer hope that someone else might be interested in genuinely assisting with development. Or failing that, maybe someone would try it out and provide some much needed feedback. Sadly though, neither happened even though it was apparent at the start that people were interested.


RailsCollab Dashboard

Right now, RailsCollab is usable as an alternative to ActiveCollab 0.7.1, with the exception of a few missing features which I have simply not got round to implementing yet. And of course it suffers from a few bugs and performance issues here and there. Still, for what it is, it works.

Will I ever do such a stupid thing like this again? I can conclusively say…. hell, no!

bookmark_borderQR-Code and the quest for the elusive decoder

After reading Mechanic #031 on the Three Hundred game ideas blog, I got thinking. Specifically, I asked myself How easy would it be to write a web-based tool for encoding and decoding data to 2d images as pixels?”.

Barcode

Luckily, this mechanism has been implemented before. The simplest example would be a barcode. However, I wanted something a bit more advanced in order to pack as much data as possible into the image, as I would imagine quite a bit of information would have to be present in each “game image”. After much scouring the web, I found two promising solutions: QRCode and Semacode. Sadly though, Semacode appeared to have pretty dodgy licensing, so I decided to steer clear of it and see what I could make of QRcode.

QRCode

QRCode was interesting, as in it was very easy to find an encoder, such as libqrencode. Unfortunately, it was very difficult finding a decoder that didn’t just run on a mobile phone (which seems to be a popular way of decoding QRCode’s). The only standalone library that could decode was written in java, oddly enough also called qrcode.

To be honest, i’m a bit put off of proceeding any further trying to get this question answered, mainly because everything seems to be written in Java, – which is fair enough, but considering my skills in programming Java are minimal, I might end up with a rather dodgy botched together solution.

Regardless, I think the concept of deciphering data from 2d images is neat. I’ll just have to find the elusive c-based decoder for QCode, or perhaps even better, find a better supported alternative system.

bookmark_borderJavascript Draw

Quite a while ago when I embarked on the Javascript Bandwagon, one of the first things I implemented was a rather simple draw test which plotted a few rectangles and other primitives on a WhatWG canvas object.

One of the little problems I encountered with the WhatWG canvas was that you really needed to play around with the values for the control points on such things as arcs and bezier curves in order to get the result you wanted. Either that, or draw everything in a vector based drawing tool and convert it to the appropriate set of drawing commands to feed into the canvas object.

Safe to say, I wasn’t so easily defeated by this little problem, and so I had a crazy idea: would it be possible to create a drawing tool written entirely in javascript which used the canvas object?

The first implementation of the JavaScript drawing tool (which I will now refer to as JSDT) resembled frankenstein on steroids. I didn’t completely understand how JavaScripts “classes” worked, so it was more or less a bunch of hap-hazardly designed functions all placed in the global namespace. Whilst it worked, it was hell to maintain, plus it lacked crucial features such as the ability to rotate and scale objects – as well as group them hierarchically.

For reference, here is a copy of the first version for you to laugh at. Note though that everything (including the manipulators) is handled in the little WhatWG canvas – no DOM in sight!

For the second version I decided to use classes from the ground-up, and make use of one of the various javascript toolkits available. In the end I chose Mootools, on account of it being lightweight and seemingly faster than the other frameworks I tried. I also planned out the design from the beginning, which helped a lot.

The second version sadly ended up being the third, as half-way through I realized that I wasn’t using the mootools “Class” object correctly. In error, I assumed attaching functions to Classes was a bit of a memory intensive operation, and thus I decided to eliminate functions from the JSDTs canvas objects, and instead place them in an “ObjectHelper” class.

Soon after, I realized how stupid I was, considering the functions are actually assigned to the object’s prototype – not its instance – and thus would be shared between each instance of the class. And thus, “ObjectHelper” was obliterated. A good thing too, as I noticed a big speed boost! I guess it just goes to show how much slower it is to use “this.object_helper.do_that(object);” rather than the more concise “object.do_that();”.

For reference, here is a copy of the third version. Its much improved over the first, and you can even change the selected objects style properties via the nice toolbox. Sadly, I haven’t yet got round to implementing the “Save” and “Load” functions, which would be the next major step in implementing the JSDT – shouldn’t be too hard to write out the canvas object list as JSON and send it to / from the server.

Safe to say, I learned a lot about the peculiarities of JavaScript when making the various iterations of the JSDT. I also experienced first hand how utterly annoying it is to have code work perfectly in one browser, yet fail miserably in the other. One interesting issue I did find with regard to the WhatWG canvas was that Apple’s Safari browser couldn’t quite handle this code:

...
canvas.moveTo(10,10);
canvas.beginPath();
canvas.lineTo(20, 10);
canvas.lineTo(20, 20);
canvas.lineTo(10, 20);
canvas.closePath();
canvas.fill();
canvas.stroke();
...

In Firefox, Mozilla, and Opera this would draw a little filled in square with a line border. In Safari however, it draws a filled in square without a line border! It seems that Safari completely forgets about the path after you either fill or stroke it, so the only workaround is to just plot the path again, i.e.:

...
canvas.moveTo(10,10);
canvas.beginPath();
canvas.lineTo(20, 10);
canvas.lineTo(20, 20);
canvas.lineTo(10, 20);
canvas.closePath();
canvas.fill();
// +++
canvas.beginPath();
canvas.lineTo(20, 10);
canvas.lineTo(20, 20);
canvas.lineTo(10, 20);
canvas.closePath();
// +++
canvas.stroke();
...

…which as you can imagine is much slower, especially if you are drawing lots of primitives!

For my next rewrite of the JSDT, I think I might look at implementing it in an abstraction layer such as OpenLazlo or the Google Web Toolkit. Hopefully then I will be able to eliminate much of the manual workarounds I have had to hack in, instead leaving it to a nice automated tool.