Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migration of unmigrated content due to installation of a new plugin

...

This page covers some background to the progress engine, the overall system design as well as the implementation algorithm.

This page is based on the original LAMS 1.1 Progress Engine document in the lams_document project. It has been updated to reflect LAMS 2.1, but the original document makes more comparisons with LAMS 1.0, so if you want to see how the progress engine has evolved, check the original document. The UML diagrams on this page have been taken from that document (as screenshots) or are in one of the MagicDraw files in lams_common/design. MagicDraw v10 is the best version for updating these diagrams - you open the .zip file from within MagicDraw to access the diagrams.

Table of Contents
maxLevel3

...

This section explains the algorithms implemented underneath to achieve the functionalities described in the above sections. To explain the algorithms, sequence diagrams, activity diagrams and code snippets will be provided wherever necessary.

...

LAMS 2.x activity page loading Mechanism

To fully understand how progress engine display the JSP of the next activity, we have to explain the activity page loading mechanism first. As you might know, the LAMS activities are classified into two big categories - complex activity and simple activity.

From the perspective of displaying these activities using JSP, we would like re-classify these activities into three major categories - Single frame JSP activity, multi-frame JSP activity and LAMS system JSP activity. These three categories and corresponding page loading strategy are explained as follows:

  • Single framed JSP activity - A single frame loading JSP is used to display the content of this type of activity. Referring back to the activity hierarchy designed in the object model, all simple activities as well as sequence activity falls into this category.
  • Multi-framed JSP activity - When we are dealing with parallel activity, single frame is no longer enough to display two or more activities on the same screen. It is therefore multi-frame needs to be initialized before the actual activity contents can be loaded into the JSP.
  • LAMS system JSP activity - A single framed JSP is also used for system activities. The difference between this category and single framed JSP activity is that the actually activity content won't be displayed directly. Instead, a LAMS page will be loaded to represent activity's content. Options activity is a good example - LAMS option page will be shown with all the sub-activities outlines and instructions rather than the contents of all optional activities.

Why did we make this classification? We want all activities contents are loaded by LAMS loading page rather than shown directly from Struts action forward. Why LAMS loading page is important? LAMS loading page has to exist because of two major reasons. Firstly, the loading page is a clean solution to add extra frame and clean unnecessary frame whenever required. Without using an intermediate loading JSP, we could not find a solution to achieve the same functionality.

Secondly, the loading page is a good place to send update progress bar message to the Flash client. In LAMS 1.0 we had the entry JSP page of each tool doing updates of the Flash progress bar. This resulted in a tight dependency between tool and the Flash progress bar, duplicate code and consequently a maintainability nightmare.

Isn't the loading page is extra overhead and makes LAMS very "chatty" (ie a lot of calls to the server)? Yes, but for the benefits it has brought use, it was worth the overhead. If usage and/or profiling show an issue in this area then we will optimise the code however the overall methodology appears sound at this stage and there are other areas we can look at for performance improvements.

Move to next activity


Figure 5 Move to Next Activity - Sequence Diagram

Above diagram shows the overall algorithm used to complete the moving from one activity to the other. This process usually triggered by clicking on the "Finished" button of a particular tool page. Originally we did Step 2 to Step 6 has to be done 8 in one transaction so as to ensure there is no inconsistent state between tool and LAMS server. After that, However when we implemented Live Edit, there was an increased chance that calculating the learner progress would fail due to some case we hadn't considered (setting up Live Edit while allowing the learners to proceed and not putting in synchronisation points which may slow down the progress engine wasn't easy). So we split the update into two transactions, so that the tool is always able to persist their data, and then it forwards to a URL in the learning web app to do all of the progress updates.

It is important to notice that LAMS travel from tool web application to lams_learning web application by via http URL redirecting. The calls. This means that any calls to the core services that are NOT in the tool's Spring contexts are available to the learning logic. The tool's do not include all the context.xml files for the core, so some of the service beans are not available.

The lams_learning is responsible for calculating the URL for next activity and forward to it. Two major algorithms, Calculate the next activity at service layer and Mapping the Activity to the URL, are hidden in above diagram, which will be explained in following sections.

This has been changed to include a call to the "CompleteActivityAction", rather than going straight to then next activityIn the diagram above, many of the calls such as Calculate Learner Progress, Put Activity in Request, etc, are really calls to other classes, but the other classes have to be hidden or the diagram would be impossible to read.

Calculate the next activity at service layer

...


Figure 6 Calculate the Next Activity - Activity Diagram

...

Note: The "recently completed activities" list referred to in the diagram doesn't seem to be used - potentially this could be dropped. The functionality is implemented by the method LearnerProgress.populateCurrentCompletedActivityList() so we could try dropping this method and test to ensure that the progress engine is still working correctly.

Mapping the Activity to the URL

...


Figure 7 Calculate the URL from Learner Progress- Activity Diagram

Once the service layer progress engine calculated the next activity to move on to and returned the learner progress, the web layer progress engine needs to figure out what is the proper URL for the next activity. Figure 7 illustrates the algorithm to fulfill this functionality.

LAMS 2.x activity page loading Mechanism

To fully understand how progress engine display the JSP of the next activity, we have to explain the activity page loading mechanism first. As you might know, the LAMS activities are classified into two big categories - complex activity and simple activity.

From the perspective of displaying these activities using JSP, we would like re-classify these activities into three major categories - Single frame JSP activity, multi-frame JSP activity and LAMS system JSP activity. These three categories and corresponding page loading strategy are explained as follows:

  • Single framed JSP activity - A single frame loading JSP is used to display the content of this type of activity. Referring back to the activity hierarchy designed in the object model, all simple activities as well as sequence activity falls into this category.
  • Multi-framed JSP activity - When we are dealing with parallel activity, single frame is no longer enough to display two or more activities on the same screen. It is therefore multi-frame needs to be initialized before the actual activity contents can be loaded into the JSP.
  • LAMS system JSP activity - A single framed JSP is also used for system activities. The difference between this category and single framed JSP activity is that the actually activity content won't be displayed directly. Instead, a LAMS page will be loaded to represent activity's content. Options activity is a good example - LAMS option page will be shown with all the sub-activities outlines and instructions rather than the contents of all optional activities.

Why did we make this classification? We want all activities contents are loaded by LAMS loading page rather than shown directly from Struts action forward. Why LAMS loading page is important? LAMS loading page has to exist because of two major reasons. Firstly, the loading page is a clean solution to add extra frame and clean unnecessary frame whenever required. Without using an intermediate loading JSP, we could not find a solution to achieve the same functionality.

Secondly, the loading page is a good place to send update progress bar message to the Flash client. If you are familiar with LAMS before 2.0, you will notice that the entry JSP page of each tool is doing updates of the Flash progress bar. This results in a tight dependency between tool and the Flash progress bar. Furthermore, update code on all tools' JSP generates duplicate code and consequently a maintainability nightmare.

Isn't the loading page is extra overhead and makes LAMS very "chatty" (ie a lot of calls to the server)? Yes, but for the benefits it has brought use, it was worth the overhead. If usage and/or profiling show an issue in this area then we will optimise the code however the overall methodology appears sound at this stage and there are other areas we can look at for performance improvements. Some calls do redirects, some do forwards. The intention is that in moving to the next activity, something should redirect to ensure that we don't accidently go back to the last screen. Normally the redirect is done via the displayTool.jsp but in other cases it is handled by the Struts "forward", which can be setup to be either a forward or a redirect. One day it would be nice to document exact at which point in the processed a redirect is done, so that we can ensure all "next activity" calls do a redirect but don't do a whole pile of redirects.

Join a lesson with Retrieving Progress Data - Needs Updating


Figure 8 Join lesson with retrieving progress data - Sequence Diagram

Based on the understanding of major progress engine algorithm and page loading mechanism, we can further the explanation of the joining lesson algorithm. The explanations of join lesson and retrieving progress data are combined because these two use cases usually happen consecutively. Once LAMS finishes joining the learner to the lesson and send the wddx acknowledgement message with the URL of loading page calculation struts action back to Flash, Flash sends the request to the LAMS server to grab entire learner progress structure to build up learner progress bar. The progress data request from Flash has to be sent after the Flash client receives the "Joined Lesson" message from LAMS because it needs to load the latest progress data.

Communication between Server progress engine and Flash Progress bar

...


Figure 9 Server and Flash Communication - Move to next activity

We have already explained the algorithm of moving to next task on the LAMS server side. How do we achieve the visual indication of the movement on the Flash progress bar? Figure 15 9 explains the detail logic behind the scene. A Flash movie update script like following will be placed is embedded on the LAMS loading page :
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0" width="1" height="1">
<param name="movie" value="../../learnerProgress_lc.swf?currentTaskId=xx">
<param name="quality" value="high">
<embed src="../../learnerProgress_lc.swf?currentTaskId=xx"
quality="high"
pluginspage="http://www.macromedia.com/go/getflashplayer"
type="application/x-shockwave-flash"
width="1"
height="1">
</object>
This script should update progress bar with current activity, attempted activity array and completed activity. Please refer to the notes on Figure 15 for the meaning of these variables. As these data has been calculated along with the server side "move to next task", we save all the extra calculation we did in LAMS 1.0. Furthermore, the (and the parallel and optional pages) and this movie opens a Flash pipe which passes the IDs for the current, attempted and completed activities. The code for the Flash swf is in the lams:Passon tag, so inclusion in a few jsps is easy.

Flash then updates the progress bar with the activity data, based on the design details that it received when the learner window was first opened. All the data has been calculated on the server side as part of the "move to next task". The data sent back to Flash is only a couple of bytessmall, which minimize minimises the Flash - Java communication cost. As a safe guard, Flash can send the request to server to restore the whole progress bar structure if there is an exception has been identified at Flash side. But we believe this won't happen very oftenissue on the Flash side.

One of the parameters passed to Flash is the design version. This is updated whenever a Live Edit is done, triggering Flash to get a new copy of the design when the version changes. This allows learners to see an updated design without having to exit/restart learner.

The code that actually moves to the next activity (on the "Loading Next Activity screen") is embedded in Javascript. If we are using the Flash progress bar then Flash calls the javascript method to advance to the next activity. This was done to eliminate timing issues we were getting between Flash updates and the JSP advancing. For this reason, the Flash progress bar had to be used in LAMS 2.0.

Non-Flash Progress Bar

In LAMS 2.1 we have introduced the Flashless learner interface (apart from Chat). If the learner is not using the Flash progress bar then the jsp calls the javascript to do the page redirect when the page is loaded. There is no need to update the non-Flash progress bar as that is generated only when the learner requests the progress display.

The non-Flash progress bar is generated using the ProgressBuilder class, which is based on the LearningDesignProcessor. During the parsing of the design, it builds a set of URLs to show completed activities. The data is then passed to a JSP for rendering. This is done every time, so we will have to watch that it doesn't become a performance issue - the code was done quickly rather than being coded to be quick. Having the work done on the server does increase the server load - normally the calculation of what should appear green, blue, etc is done in Flash and hence is done in the client. But it isn't done on every progress (as it in Flash) so hopefully it won't be a big issue.

Authoring Preview

When an author runs a preview, it actually runs a complete lesson, with a single learner in the class. There is no monitoring client. Apart from the differences mentioned for Gates and Grouping below, the following differences apply to Preview.

...

At present, the lesson and progress data are not cached, although the core User objects are cached. These are obvious candidates for caching, as they are complex structures and are required on every calculation of the next activity. Just putting the objects straight into the user's normal HttpSession or even the SharedSession doesn't work well. The HttpSession varies from web-app to web-app and some of the code to execute the "next" functionality is run within the tool's web-app, although the code itself lives in the lams-learning.jar. Putting it in the SharedSession would avoid this, but then we have to have two different entries for the lesson and progress data for the preview screen and the learner screen as both can be running simultaneously. Also, putting the lesson in the SharedSession is not a good idea as the Lesson is the same for all the users in the Lesson and potentially we could be caching a Learning Design (attached to the Lesson) which is now out of date due to a Live Edit. So the Lesson and the LearningDesign will probably need to be cached using the JBoss cache, which interacts with Hibernate so that the object in the cache is up to date.

In general, there is a lot of "put activity in the request", "get learner progress somehow", "put activity id/learning design id in the request parameters", etc in the progress engine. Originally it was carefully tuned so that each system screen got only what it needed, but then we'd change the screen to do more and we'd need more parameters, etc so it grew higglepiggldy. When we look at caching the progress data then we need to clean up where we put the activity in the request.

Making System Tools More Pluggable

...