Surprisingly good position in Dokeos-Moodle-ILIAS comparison

July, 4 2008

I was playing around a little bit with a code metrics tool on the Ohloh website and, although I’m sure there’s some kind of arguable element there as some included libraries add a lot of “noise” in code contributions, I was happily surprised to see that Dokeos isn’t doing bad at all and is starting to get back at Moodle, in terms of code, contributors and global activity. I’ll let you check that by yourselves (following the “code metrics tool” link, or just looking at the screenshots below).

Before you start thinking that this must be a distorted comparison as it is made by a Dokeos developer, I just want to let you know that Ohloh.net is totally independent in this case. I just ran a comparison because there was a tool to do that automatically, and thought the results were interesting and at the advantage of Dokeos and, as such, might be interesting to post here. I totally realise that there is no obvious conclusion to be taken out of these results.

In the screenshots below, Dokeos is marked as red, Moodle as green and ILIAS as blue. Claroline, which I have left out of the comparison because I can only compare three projects at a time, has about the same level in the three graphs as ILIAS (in blue).

The first graph is about the codebase (number of lines of code). The second is about activity in terms of code submissions. The third one is about the number of active contributors. As you will see, when Dokeos is not on top, it’s getting there, slowly. Lines of code for the three projects are all increasing at about the same rate though…

Dokeos-Moodle-ILIAS code comparison
Dokeos-Moodle-ILIAS code comparison
Dokeos-Moodle-ILIAS activity comparison
Dokeos-Moodle-ILIAS activity comparison
Dokeos-Moodle-ILIAS active contributors comparison
Dokeos-Moodle-ILIAS active contributors comparison

The Dokeos position in that race is not surprising because I feel like crap, instead, it is surprising because it is generally much more heard of Moodle as an active open-source project than Dokeos, so theoretically, Moodle really ought to be on top of these three graphs… go figure!

From the graphs, it looks like 2006 has been a tremendous year for Moodle, and then it started slowing down a little. I don’t know much about ILIAS’ history, but I recently heard from a colleague that had had to compare Dokeos and ILIAS that ILIAS was no match (big flame wars starting here ;))

Anyway, the story of Dokeos still has a bunch of nice surprises to come as well. I hope the same is true for our competitors.

Just for the fun, if you want to compare Dokeos to Claroline and Ganesha, follow this link.


Dokeos in Peru

July, 4 2008

In case it would be of any interest to you, I am currently developing a kind of “branch” of Dokeos (although nothing legally-binding about the branch stuff) in Latin America, and more specifically in Peru.

Peru is still what I would call a developing country, so at the same time it is hard to get used to (living there) and possibly excellent for future business opportunities. Of course, “developing” comes from “development”, and “development” means investments, which means a lot of money could be made (theoretically) from being in the right place at the right time.

Although I feel I’m still a bit ahead of “the right time”, I’ve invested a considerable amount of my time in developing the presence of Dokeos locally, and until now (about a year on) it’s not been very rewarding.

As I’m writing these lines, however, I just finished my first installation of Dokeos, or rather its videoconference module, on a Fedora 7 system. It ended up working nicely, but there wasn’t really any other expected outcome.

However, the interesting bit here is that it’s my first contract in Peru (most of my work so far has been a continuation of my work in Belgium) and it comes with a lot of simultaneous requests for information. I don’t know exactly why it’s all starting at the same time, but it is. So I might only have finished my first Peruvian job, but I’m still with 4 very serious leads for large-scale installations and training sessions, and a few more of unqualified leads, plus a bunch of people that know they can act as resellers of my (or should I say “our” as we’re a company of three now) services and take a nice commission.

So today, I might only being up to my first install, I am really positive about the future!

One of my serious leads is actually for software development, and is a request for a quote about the development of an add-on to the videoconference tool that will enable teachers to pass the video and voice to the user to ask a question. The feature has been requested a few times in the past, but we never managed to suggest a development time that satisfied the customers. However, now we have a much more reliable videoconferencing system (thanks to Arnaud Ligot and Frédéric Burlet), this might be much easier to work on (and so, cheaper). If you have an interest in this feature and would like to contribute to make it possible, just give me a shout. Otherwise, there is still a possibility that this client will not be able to finance the development and that we just leave it for another client, later on…

It always surprises me, though, how people are happy to pay 10u a year for a finished product, but reluctant to pay 2u for the development of the only missing feature in a product that costs 1u… (values provided for demonstration purposes, it doesn’t match anything).

Well, anyway, the point of this article was to let you know a little bit about my stuff, locally. The next articles will be a bunch of incredibly technical stuff, so this was just a big breath before the dive.


Dokeos 1.8.5 released!

June, 13 2008

Dokeos 1.8.5 has been released, after a long 8 months development! Check it out on http://www.dokeos.com/download.php

There’s a lot to say, so I won’t comment about the release itself in this post. You can find out more about this release and what it brings you on the official website, by following the link on the right panel.

We are sorry to have kept you waiting for so long for a new version, but we’re sure you’ll understand why when using it!


Dokeos 1.8.5 released… kind of!

June, 12 2008

It’s still a bit premature because we’d like to try it out a few times more before officially announcing it on the website, so if you want to help, feel free to download your version from here: http://www.dokeos.com/download/dokeos-1.8.5.zip

In a few hours from now we will make the official announcement, so the official release date will be the 12th of June anyway.

If you happen to witness some wierd thing in the install or upgrade procedure, please, let me know as soon as possible!

Otherwise, just enjoy the ride. Dokeos 1.8.5 is concrete-stable, and this is a stability we will now be able to build on for the next version.


What’s left before 1.8.5 stable…

June, 5 2008

Not that I’ve been too busy on Dokeos lately (I tend to take my mind off Dokeos for a couple of days after a release), but it’s going to come back very fast now as we are warming up for the last run to Dokeos 1.8.5 stable.

So, what’s on the menu?

Well, apparently there are still *some* bugs about the course copy and SCORM export somehow. Thomas filed a bug for me about this. Although I did really worked my *** off right before RC1, it seems like something is still wrong, so I’ll have to get back to it.

Then apparently we missed a few options in the new “read-only” mode for documents, so I’m going to have a look at that too.

I also have to change a little bit the learning path default view, to reduce the header drastically. The rest will stay, but the header frame will be reduced to 1 pixel (if not removed completely - I can’t see why I couldn’t) and a new button “Back to course” will appear, sending the user… well, back to the course homepage. This comes as *many* (if not all) of our clients are complaining that:

  1. when they develop custom styles, if the header is larger than the default styles, the frames structure of the learning path tool breaks it all
  2. the header takes too much space, while all the user wants is to be able to see the contents of this learning path
  3. it’s pretty ugly to have a framed design. Damnit, we’re in 2008!*

There might be some other minor things I should worry about, like getting a bit more of that multi-campus feature working**, even if it’s not going to be activated in 1.8.5 officially.

In the meantime, I might be up to my first sale here in Perú. I’ll give more info about that (if I can) later on.

As always, I’ll keep you updated as soon as 1.8.5 is out or close-to-being-out.

* I actually tried very hard to get rid of the framed design in Dokeos 1.8.5, but ended up fighting against the different types of contents we received from external sources. If there’s a CSS specialist amongst my readers (I really mean specialist), I want to talk to him!

** The multi-campus feature should allow one campus to be used with different URLs at the same time, with different (limited) configurations, including different stylesheets and sessions.
It’s not working yet but the database structure is ready to accomodate the feature.


Call for White Papers for SCORM 2.0

June, 2 2008

LETSI, Learning Education Training Systems Interoperability, is entering a phase of study for the next version of SCORM, version 2.0.

Of course, given the little level of adoption of SCORM 2004 (or 1.3), this might seem a little premature for some, but the making of such a large norm takes time, so it’s probably better to get started early.

The 2.0 version is said (in the announcement of the Call for White Papers ) “to support the use of open software standards in learning technology”, which is a nice turn of event as, although SCORM 1.x was never against open standards, it never actually pretended to focus or support them. It just used “JavaScript” (which is not really standard in this appellation) and supposedly HTML or anything that would allow the use of JavaScript.

Dokeos hasn’t got any White Paper to submit though, mostly because we didn’t implement SCORM 2004 yet, so it’s pretty difficult to know what’s missing in the latest version… The White Papers submission deadline is August, 15 so we won’t be able to first support SCORM 2004 and then start thinking about things we would like to see there, but it would have been a pleasure for me to participate in the making of SCORM 2.0.


Updated Dokeos 1.8.5 page

May, 29 2008

I’ve updated the Dokeos 1.8.5 page to reflect the fact that we now have a Release Candidate and are very close to the stable release.

This is a time for us (developers) to take a deep breath and analyse things with the satisfaction of someone having done a nice job. Nevertheless, we are very careful not to miss anything, but as usual we count on your help to spot things that really are difficult to see.

We are already thinking about the developments for 1.8.6, which will be only a few and will concentrate (if everything goes as expected) on exercises - making it easier and more reliable to build exams using Dokeos - and web services - making it easier to connect Dokeos to other web systems.


Dokeos 1.8.5 RC1, possible last changes and the close future

May, 27 2008

We officially released 1.8.5 RC1 tonight, although we might alter the package just for two little microscopic changes tomorrow morning (one concerning SCORM export on Dokeos installs that use a subdirectory of the web server document root, and the other implementing a default hiding of the audiorecorder for the learning path building tool).

I think there’s not much to say, other than it’s a *great* unstable release. I find it amazing how much we can progress with a good team. Not in terms of features (there are new features, and they are all interesting), not even in terms of bug fixing (there are tons of bugfixes, I can’t even remember all of them), but in terms of general stability and structure. From Dokeos 1.6, which was pretty much close to a “toy” software (I might be overdoing it a little bit here ;-)), we got into something… really amazing. We have now a full professional e-learning suite that lets you use pretty much any kind of
media, with an incredibly easy-to-use interface, all in a package that can handle without a problem up to 175000 users. It’s just freaky…

We still know how to improve it even more, but now we’re focusing on testing for 1.8.5 stable (which we will probably release within the two next weeks), so feel free to help us get faster there…

Into 1.8.5, we’ve shipped an incredible amount of security improvements, warning and notice messages (that would otherwise make the logs much larger than necessary) and fixed tons of bugs.

So now the question is “Why do others do more sales?”. Well, a huge part of this answer is: marketing. We have to do a huge effort in marketing in the next few months if we want to be able to continue the Dokeos development (which is very expensive, as is all kind of software that you don’t sell in itself and which doesn’t bring much free help). You can have the best product ever, if nobody knows it, it will be totally forgotten sooner than you think.

So if you have leads, if you think your company might benefit from Dokeos and… - why do I want to say “…if no one else can help, and if you can find them…” ? - … at the same time help a great open-source platform to develop… well, don’t hesitate to contact me! It will be my pleasure to follow the lead.


Adding repetitive events to a simple PHP agenda system

May, 21 2008

Introduction

To prepare for RC1, I have to submit the latest database changes for this release. The objective of these changes is specifically to add the management of repeated events to a simple agenda system that doesn’t have them.

So, what’s the big deal? Well, there are two ways I was thinking repeated agenda events could be handled…

  1. create as many events as the repetition needs
  2. add repetition data to the original event to say “this is a repetitive event and it repeats this way…”

Let’s have a look at those two possible ways to do it

“Create many events” solution

The solution seems easy, after all. You just create a series of events and limit the final date to something not too far away, and there you go, you can continue using your system as usual.

There are two shortcomings to this system:

  1. In some cases, you will get *many* events which, if they contain a long description, can eat up your disk space fast (imagine you attach a 30K picture to the event and repeat it every week for the next 10 years, that’s 15MB of data for a simple illustrated event - and 30K is *not* much)
  2. How do you know which event was the first one? And so how do you keep a relationship between the “father” event and its offsprings? And so how do you delete the repeated event if you realise you made a mistake?

If point 2 can easily be avoided by adding a “parent” field to my table structure, and sticking it to each offspring, problem 1 isn’t easily solved.

“Add repetition expression to the original event” solution

If this solution removes the problem 1 from the previous idea, it introduces a few additional flaws:

  1. How do you tell, from a simple week view, if there is a repeated event today or not?
  2. How do you structure the information related to the “repetition” information?
  3. How do you remove one occurrence of the repetition (say one weekly event is cancelled because of the host being in hospital)?

None of these problems is solved easily…

Fortunately, there is a reference: WebCal! WebCal is *the* open-source software that deals with calendars and events of any kind, so it has to have a good solution for us, hasn’t it?

The WebCal solution

WebCal took the second idea but, probably after realising the three shortcomings, had a brilliant idea: store the repeated event’s information into a separate table.

This way of doing things, if implemented properly, ensures:

  1. It is easy to retrieve repeated events as it’s another table, with a much smaller amount of events (however, calculating daily events from repetition metadata might be resource-consuming)
  2. We can store the repetition information in the new table, with a proper way to structure this data (and to store it, retrieve it, update it)
  3. We can use *another* table again to store the exceptions to the repetition cycle
  4. There is no modification to the existing events table

In fact, one the of the most annoying elements of the second solution was that if a lot of events were recorded in the calendar, retrieval of repeated events would potentially highly suffer from other “noise” data.

Having them in a separate table will ensure we only get a few (after all, you can’t really repeat a lot more than 10 events per week, as it will fill your week already!) and our queries will be much faster to check if there is a repeated event today, or this week.

However, this will still use a lot of processing power when calculating when the events are repeated.

This is somehow helped by the fact that they restricted the types of repetition to a minimum of a day, with the following criterias:

daily, monthlyByDate, monthlyByDay, monthlyByDayR, weekly, yearly

Where monthlyByDayR means “monthly by day, restricted” to say that it can be only the second Monday of every month, for example.

We will not implement monthlyByDay nor MonthlyByDayR in this first implementation though, so for time reasons, we will only provide daily, monthlyByDate, weekly and yearly at first.

Implementing it inside Dokeos

So now we have the idea, let’s implement it inside Dokeos.

In Dokeos, we have a *very* simple calendar application. Basically, you add an event, it has a start time, an end time and a description. The table definition looks like this:

CREATE TABLE course_agenda (
id int unsigned NOT NULL auto_increment,
title varchar(200) NOT NULL,
content text,
start_date datetime NOT NULL default ‘0000-00-00 00:00:00′,
end_date datetime NOT NULL default ‘0000-00-00 00:00:00′,
PRIMARY KEY (id)
)

We also happen to have a personal agenda, which is outside of the course context. The table for this one is defined as:

CREATE TABLE personal_agenda (
id int NOT NULL auto_increment,
user int unsigned,
title text,
`text` text,
`date` datetime default NULL,
enddate datetime default NULL,
course varchar(255),
UNIQUE KEY id (id)
);

(so we have a reference to the user id and the course id here, as well as an additional description text - this structure is very wrong - it wasn’t me, I swear! - and very MySQL-dependent because of the backticks to escape fields that use reserved keywords)

Anyway, so here the idea is that we will have to duplicate the new tables as well, because a personal agenda is global, while a course agenda is restricted to the context of a course.

However, any user can see a screen with the events from his personal agenda *and* the ones from all the courses he’s subscribed to. So even if we don’t have a lot of repeated events, it is still a considerable query we have to do to get them all.
So we have to add, on both sides, two tables with the something approaching the following structure (coming from the WebCalendar code):

CREATE TABLE webcal_entry_repeats (
cal_id INT DEFAULT 0 NOT NULL,
cal_type VARCHAR(20),
cal_end INT,
cal_frequency INT DEFAULT 1,
cal_days CHAR(7),
PRIMARY KEY (cal_id)
);

CREATE TABLE webcal_entry_repeats_not (
cal_id INT NOT NULL,
cal_date INT NOT NULL,
PRIMARY KEY ( cal_id, cal_date )
);

Now we have the structure. How does the interface reflect those additional possibilities?

The insertion side

Well if we keep it simple, we will only have to provide a tickbox to say if this event is repeated or not, and a drop-down list with the three options we are offering: daily, monthlyByDate, weekly or yearly. Finally, an absolute end will have to be given, which we will ask the user to fill in.

This data will then go right to the new database table and, using the current event as a start date, will complete the insertion part of the new feature.

On the querying side though, things are going to be much more complex.

The querying side

Whenever a user goes on a calendar page, he needs to see the repeated events. If a daily view shouldn’t be too complex, a monthly view adds just a little bit to it: we have to check over a wider area.

Let’s start with a daily view. Let’s say we are querying for everything that is happening on the 21st of May. Let’s also say we are only looking at the personal agenda side.

The first thing we do is check for normal events. No worries there, we already do that.

Then, we want to check for repeated events. Because we have a separate table for these, we can easily check all the repeated events that:

  1. have a start date anterior, or equal to the 21st of May ($may21start = mktime(0,0,0,5,21,date(’Y'));)
  2. have an end date posterior, or equal to the 21st of May ($may21end = mktime(0,0,0,5,21,date(’Y'))-1;)

Once we have those (let’s say we have only one), we start with the tricky part: calculating whether the repetition occurs today or not. We will use PHP dates massively here to provide an effective date calculation.

As previously mentioned, we have only four types of repetition here, so we can find a formula for each of these types (forgetting for now about exceptions), and create a function for each:

daily

Well, it will happen today considering the conditions above are met, that’s for sure, so consider it part of today’s view. You will still have to calculate the starting and ending time of this new event though. That would look as something like this:

$time_orig_h = date('H',$orig_start);
$time_orig_m = date('i',$orig_start);
$time_orig_s = date('s',$orig_start);
$int_time = (($time_orig_h*60)+$time_orig_m)*60+$time_orig_s; //time in seconds since 00:00:00
$span = $orig_end - $orig_start; //total seconds between start and stop of original event
$current_start =$start + $int_time; //unixtimestamp start of today's event
$current_stop = $start+$int_time+$span; //unixtimestamp stop of today's event

weekly

$time_orig = date('Y/n/W/j/N/G/i/s',$event_start_time);
list($y_orig,$m_orig,$w_orig,$d_orig,$dw_orig,$h_orig,$n_orig,$s_orig) = split('/',$time_orig);
$time_now = date('Y/n/W/j/N/G/i/s',time());
list($y_now,$m_now,$w_now,$d_now,$dw_now,$h_now,$n_now,$s_now) = split('/',$time_now);
if((($y_now>$y_orig) OR (($y_now == $y_orig) && ($w_now>$w_orig))) && ($dw_orig == $dw_now))
{
  $time_orig_end = date('Y/n/W/j/N/G/i/s',$event_end_time);
  list($y_orig_e,$m_orig_e,$w_orig_e,$d_orig_e,$dw_orig_e,$h_orig_e,$n_orig_e,$s_orig_e) = split('/',$time_orig_end);
  add_event_to_view(
    $event_title,
    mktime($h_orig,$n_orig,$s_orig,$m_now,$d_orig,$y_now),
    mktime($h_orig_e,$n_orig_e,$s_orig_e,$m_now,$d_orig_e,$y_now)
  );
}

monthlyByDate

$time_orig = date('Y/n/j/G/i/s',$event_start_time);
list($y_orig,$m_orig,$d_orig,$h_orig,$n_orig,$s_orig) = split('/',$time_orig);
$time_now = date('Y/n/j/G/i/s',time());
list($y_now,$m_now,$d_now,$h_now,$n_now,$s_now) = split('/',$time_now);
if((($y_now>$y_orig) OR (($y_now == $y_orig) && ($m_now>$m_orig))) && ($d_orig == $d_now))
{
  $time_orig_end = date('Y/n/j/G/i/s',$event_end_time);
  list($y_orig_e,$m_orig_e,$d_orig_e,$h_orig_e,$n_orig_e,$s_orig_e) = split('/',$time_orig_end);
  add_event_to_view(
    $event_title,
    mktime($h_orig,$n_orig,$s_orig,$m_now,$d_orig,$y_now),
    mktime($h_orig_e,$n_orig_e,$s_orig_e,$m_now,$d_orig_e,$y_now)
  );
}

yearly

$time_orig = date('Y/n/j/z/G/i/s',$event_start_time);
list($y_orig,$m_orig,$d_orig,$dy_orig,$h_orig,$n_orig,$s_orig) = split('/',$time_orig);
$time_now = date('Y/n/j/z/G/i/s',time());
list($y_now,$m_now,$d_now,$dy_now,$h_now,$n_now,$s_now) = split('/',$time_now);
if((($y_now>$y_orig) OR (($y_now == $y_orig) && ($m_now>$m_orig))) && ($dy_orig == $dy_now))
{
  $time_orig_end = date('Y/n/j/G/i/s',$event_end_time);
  list($y_orig_e,$m_orig_e,$d_orig_e,$dy_orig_e,$h_orig_e,$n_orig_e,$s_orig_e) = split('/',$time_orig_end);
  add_event_to_view(
    $event_title,
    mktime($h_orig,$n_orig,$s_orig,$m_now,$d_orig,$y_now),
    mktime($h_orig_e,$n_orig_e,$s_orig_e,$m_now,$d_orig_e,$y_now)
  );
}

For a one-day view, we will use the four formulas as switches inside a checker function, repeat_check_today(), that will either get the event start time and end time or input them directly into some kind of session array, or even print them to screen.

That’s about the same idea for week and month views, so I won’t describe them right now. I didn’t dive into the Dokeos code much, sorry about that.

Yes, OK, but hold on just a second…

I don’t know what you think about all this, but I thought it was a mind-buggingly complicated set of algorithms (and they are even simpified in this example), so I spend a few *hours* trying to make everything perfect, and then I tried it… awfully slow.

And after one more hour of thinking, I finally got back to the first solution. Well, not completely. I mixed the first, the second and the third, so what I have now is this final solution (that works, that is fast and easy to implement).

The chosen solution: a little bit of everything

In short, I add a “parent_event_id” field to the initial agenda table, so I can create any number of events that *depend* on a first parent.

Then I keep my additional tables repeat and repeat_not, to be able to store the corresponding expression that explains how the repetition works, and when there is an exception.

When inserting, I just offer the possibility to repeat the event at a certain frequency until an end date. This triggers the insertion of one parent event (nothing special, nothing in the parent_event_id field), and then I parse the frequency and

  1. record the repetition expression in the “agenda_repeat” table
  2. create as many repeated events as asked for in “agenda”, each of them having a parent_event_id of the parent event

When querying

This means that there is very little to change to the way my application works in order to use those repeated events: they are just displayed as normal events.

If you want to make it possible to get to the parent event, you can check if the parent_event_id is not null, and then display a link to the parent event.

When editing, you actually never offer the possibility to “edit” an event “repetition-wise”, because it would be very difficult to handle. If the user has made a mistake, he can just delete the parent event and all other events will be deleted, and then he can create another one that fixes the previous problem.

If you want to edit one of the child events, you can, it is just a copy related to the parent, but then you can mention specific information about one day’s event.

When deleting, I have left it very limited so far, so you cannot delete one single child event (I am not yet handling repetition exception). You have to mention something in the event’s description to say it’s been cancelled on that specific day (this exception isn’t preserved in iCal exports though).

If you delete the parent event, all children will be deleted as well, whether they have been changed or not.

Conclusion

Although the second solution seemed clean enough, it added a lot of problems of integration with the agenda already there in Dokeos 1.8 (which is quite bad in itself, I must admit).

It also prevents the alteration of any of the event’s repetition, but considering the fact that it is a repeated event and that it has to offer export features (to iCal, for example), there must be a way to express clearly how it is repeated, so we definitely need to have that information. Clicking on one repeated item has to show the details of the original item with an updated time information, and cannot allow for edition (otherwise it’s not clear what we are editing).

There is definitely still room for improvement in the interface provided to the user, but I am quite convinced that structure put in place allow for *any* kind of change now.

If you wanna try out Dokeos 1.8.5 (in beta version at time of writing), head to http://demo.dokeos.com/


Dokeos 1.8.5 Beta 2 available

May, 9 2008

Alright, so I did release a little brother for Dokeos 1.8.5 Beta today. We needed it for a customer of ours which is in development phase, and we had made a series of small but useful improvements to the Beta 1, so we decided that “why not?” and that a little Beta 2 couldn’t be harmful.

It can be downloaded from here

Basically, improvements are:

  • LDAP (tested in authenticated mode and added a field to define which value to search for in trying to recognize a teacher)
  • forum post alerts by e-mail
  • improved interface for creating new documents
  • removal of *many* notice-level warnings
  • speed and info improvements on users lists generation
  • isolation of exercises (was causing problems when opening an exercise from a link)
  • several fixes to buggy statistics for single DB mode
  • fixed courses descriptions bug (couldn’t edit course descriptions)
  • added informational messages in course copy to avoid user confusion

We are still working hard to try and get a definitive stable version out by the end of May or early June. We still intend to add several features to the whole thing (like *maybe* some kind of web services interface) which do not alter existing functions.

Can’t promise anything right now, but I’ll keep you informed.