Hi Josh,
I've been using a modified version of the Macromedia API for a long
time and swapped recently to pipwerk's.
I'm very happy with this change (thanks Philip for your work!), but I
found myself with the same issue as you, this API doesn't
automatically set the time.
Normally, I don't like the flash movie to comunicate directly with the
lms, or to trigger the API functions, so the solution I got is very
different from yours. I hope the solution may be useful as well to
other people, because it works well with both scorm 1.2 and 2004 and
once you've included the code in the API you don't need to worry about
saving the time, the API does it by itself.
Before giving you the code I just want to let you know that I've just
done some copy-paste, so all the credit should go to the Macromedia
guys, Claude Ostyn and, of course, Philip Hutchison.
(I'll keep some lines from Philip's code before each part of the code
I added, so you know where it goes)
The first step is to record the date when initialising the connection:
pipwerks.SCORM.connection.initialize = function(){
var success = false,
scorm = pipwerks.SCORM,
completionStatus = pipwerks.SCORM.data.completionStatus,
trace = pipwerks.UTILS.trace,
makeBoolean = pipwerks.UTILS.StringToBoolean,
debug = pipwerks.SCORM.debug,
traceMsgPrefix = "SCORM.connection.initialize ",
//next line added to record the time when the connection is
initialized
g_dtmInitialized = new Date();
...
The second and last step is to report the session time when
terminating the connection:
var success = false,
scorm = pipwerks.SCORM,
exitStatus = pipwerks.SCORM.data.exitStatus,
completionStatus = pipwerks.SCORM.data.completionStatus,
trace = pipwerks.UTILS.trace,
makeBoolean = pipwerks.UTILS.StringToBoolean,
debug = pipwerks.SCORM.debug,
traceMsgPrefix = "SCORM.connection.terminate ";
if(scorm.connection.isActive){
//next line added to set the session time
SCOReportSessionTime();
...
And you must add the code for the function called (I've put it at the
end of the file):
function SCOReportSessionTime() {
var success = false;
var dtm = new Date();
//in the next line you substract the time recorded when initialising
the connection from the present time.
var n = dtm.getTime() - g_dtmInitialized.getTime();
switch(scorm.version){
//the time format is different on scorm 1.2 or 2004, so we use
different conversions depending on the case
case "1.2" : success =
scorm.set("cmi.core.session_time",MillisecondsToCMIDuration(n));
break;
case "2004": success =
scorm.set("cmi.session_time",centisecsToISODuration(Math.floor(n/
10))); break;
}
}
//function to convert time to scorm 1.2 time format
function MillisecondsToCMIDuration(n) {
//Convert duration from milliseconds to 0000:00:00.00 format
var hms = "";
var dtm = new Date(); dtm.setTime(n);
var h = "0" + Math.floor(n / 3600000);
var m = "0" + dtm.getMinutes();
var s = "0" + dtm.getSeconds();
hms = h.substr(h.length-2)+":"+m.substr(m.length-2)+":";
hms += s.substr(s.length-2);
return hms
}
//function to convert time to scorm 2004 time format
function centisecsToISODuration(n) {
// Note: SCORM and IEEE 1484.11.1 require centisec precision
// Months calculated by approximation based on average number
// of days over 4 years (365*4+1), not counting the extra day
// every 1000 years. If a reference date was available,
// the calculation could be more precise, but becomes complex,
// since the exact result depends on where the reference date
// falls within the period (e.g. beginning, end or ???)
// 1 year ~ (365*4+1)/4*60*60*24*100 = 3155760000 centiseconds
// 1 month ~ (365*4+1)/48*60*60*24*100 = 262980000 centiseconds
// 1 day = 8640000 centiseconds
// 1 hour = 360000 centiseconds
// 1 minute = 6000 centiseconds
n = Math.max(n,0); // there is no such thing as a negative
duration
var str = "P";
var nCs = n;
// Next set of operations uses whole seconds
var nY = Math.floor(nCs /
3155760000);
nCs -= nY *
3155760000;
var nM = Math.floor(nCs / 262980000);
nCs -= nM * 262980000;
var nD = Math.floor(nCs / 8640000);
nCs -= nD * 8640000;
var nH = Math.floor(nCs / 360000);
nCs -= nH * 360000;
var nMin = Math.floor(nCs /6000);
nCs -= nMin * 6000
// Now we can construct string
if (nY > 0) str += nY + "Y";
if (nM > 0) str += nM + "M";
if (nD > 0) str += nD + "D";
if ((nH > 0) || (nMin > 0) || (nCs > 0)) {
str += "T";
if (nH > 0) str += nH + "H";
if (nMin > 0) str += nMin + "M";
if (nCs > 0) str += (nCs / 100) + "S";
}
if (str == "P") str = "PT0H0M0S";
// technically PT0S should do but SCORM test suite assumes
longer form.
return str;
}
I'll be keeping an eye on this topic, so if anyone has any question
I'll be happy to try to help! I hope my english to be understandable
enough!