// comSwf.as by Apolo Pena // Description: Controls AICC communication via HACP for Flash based Courseware. var useErrorHandling = true; // toggle this off to troubleshoot var startTime = getTimer(); var exitAU = 0; var error = "NOT_SET"; var aicc_url = "NOT_SET"; var aicc_sid = "NOT_SET"; var aicc_data = "NOT_SET"; var sendCommand = 0; var timeout = 60; // server timeout in seconds for HACP calls function getTimeElapsed() { // assumes startTime has been set already var secs = 0; var mins = 0; var hours = 0; var fSecs = 0; var fMins = 0; var fHours = 0; var secondsElapsed = 0; secondsElapsed = Math.floor((getTimer()-startTime)/1000); hours = Math.floor(secondsElapsed/3600); if (secondsElapsed%3600 != secondsElapsed) { mins = secondsElapsed%3600; } else { mins = Math.floor(secondsElapsed/60); } if (secondsElapsed%60 != secondsElapsed) { secs = secondsElapsed%60; } else { secs = secondsElapsed; } // format it if (secs < 10) { fSecs = "0"+secs; } else { fSecs = secs; } if (mins < 10) { fMins = "0"+mins; } else { fMins = mins; } if (hours < 10) { fHours = "0"+hours; } else { fHours = hours; } timeStamp = fHours+":"+fMins+":"+fSecs; return timeStamp; } function triggerExitAU () { _level0.dataHolder.error= ""; _level0.dataHolder.command = "exitAU"; _level0.dataHolder.version = "2.0"; _level0.dataHolder.session_id = aicc_sid; showMsg("ExitAU command is being issued to the LMS"); _level0.checkForData(new Array("_level0.dataHolder.error"), "JAVASCRIPT", "clearparam"); _level0.dataHolder.loadVariables(aicc_url, "POST"); showMsg("ExitAU command has been sent"); } function initialize(stepBystep) { showMsg("INITIALIZING..."); with (this) { initVarsArr = new Array(); initVarsArr.push("_level0.aicc_url"); initVarsArr.push("_level0.aicc_sid"); } checkForData(_level0.initVarsArr, "JAVASCRIPT"); fscommand("Init"); } function checkForData(varArr, command, action) { showMsg("checkForData called with an action of: "+action +"\ncheckForData is checking for the value of "+ varArr[0] + " to change"); this.dataChecker.action = action; this.dataChecker.command = command; this.dataChecker.varsToCheck = varArr; this.dataChecker.gotoAndPlay("data_loop"); } function listVars (obj){ for(var i in obj){ showMsg(obj+"."+i+" is a "+typeof(obj[i])+" and has a value of "+obj[i]); } } function getAICCData(COMType) { if (COMType == "getURL()") { command="getparam"; version="2.0"; session_id = aicc_sid; _level0.showMsg("getAICCData() --> sending HACP request via "+COMType+" to: "+aicc_url+"\nsession_id="+session_id); getURL(aicc_url, "_blank", "POST"); delete command; delete version; delete session_id; } else if (COMType == "activeX") { var errorVars = new Array("_level0.dataHolder.error"); command="getparam"; version="2.0"; session_id = aicc_sid; checkForData(_level0.errorVars, "JAVASCRIPT"); _level0.showMsg("getAICCData() --> sending HACP request via "+COMType+" to: "+aicc_url+"\nsession_id="+session_id); fscommand("hacpRequest", aicc_url+"|"+command+"|"+escape(session_id)+"|"+version); delete command; delete version; delete session_id; } else { // LOADVARIABLES CALLED HERE //_level0.dataHolder.command="getparam"; // this is set from js now _level0.dataHolder.version="2.0"; _level0.dataHolder.session_id = aicc_sid; _level0.dataHolder.loadVariables(aicc_url, "POST"); _level0.showMsg("getAICCData() sent HACP request via loadVariables() to: "+aicc_url+"\nsession_id="+_level0.dataHolder.session_id); } } function sendAICCData (COMType, time) { // same as putparam, args not yet implemented _level0.dataHolder.error= ""; //_level0.dataHolder.command = "putparam"; // this is set from js now _level0.dataHolder.version = "2.0"; _level0.dataHolder.session_id = aicc_sid; _level0.dataHolder.aicc_data="[core]\nLesson_Status="+ dataHolder.lesson_status +"\nLesson_Location="+dataHolder.lesson_location+"\nscore="+dataHolder.score+"\ntime="+getTimeElapsed()+"\n[Core_Lesson]\nsuspenddatastr="+dataHolder.suspenddatastr+"\n"; _level0.dataHolder.loadVariables(aicc_url, "POST"); sendCommand = 0; showMsg("sendAICCData says --> putparam command sent to LMS, aicc_data="+_level0.dataHolder.aicc_data+"\n_level0.sendCommand="+sendCommand); } function parseHACPReturn (str, coreType) { origLinesOfText = str.split("\n"); // preserve case, the is the data that will actually be dissected and returned str = str.toLowerCase(); // ignore case to compensate for variations in case in various LMS's showMsg("parseHACPReturn() says --> string to parse is: "+str); if (str.indexOf("[core]") == -1) { showMsg("parseHACPReturn aborted --> string to parse is not valid and does not contain [core]"); return; } var startSliceFound = false; var endSliceFound = false; var validCoreType = -1; var startSlice = ""; var endSlice = ""; var dataObj = new Object; var nameValuePairs = new Array(); var coreTypes = new Array("core", "core_lesson", "core_vendor", "student_data"); for (var i = 0; i < coreTypes.length; i++) { if (coreType == coreTypes[i]) { validCoreType = i; } } var startSlice = coreType; if (validCoreType == -1) { _level0.showMsg("parseHACPReturn() failed --> "+coreType+" is not a valid argument"); return; } var linesOfText = str.split("\n"); var len = linesOfText.length; /* BEGIN BUGFIX 11/22/05 - Ap: detect if the core type is the last one in the return (i.e. [core_lesson] might be the last tag) start by determining which core types are NOT present in the return */ var presentCoreTypes = new Array(); // track the core types that are present in the return var coreTypeIsValid = false; // flag to ensure parse request is valid for (var i = 0; i < coreTypes.length; i++) { if (str.indexOf("[" + coreTypes[i] + "]") != -1) { presentCoreTypes.push(coreTypes[i]); if (coreType == coreTypes[i]) { coreTypeIsValid = true; } } } // error handling: make sure the coreType sent to this function is present in the HACP return if (!coreTypeIsValid) { _level0.showMsg("parseHACPReturn() failed --> "+coreType+" does not exist in the HACP return"); return; } /* now that we know which core types are present and that the parse request is valid, we need to figure out which is the bottomost one (the one that will have no [core..] tag below it). start by looping backwards through the linesOfText untill we hit the bottomost coretype and then store that */ var lastCoreType = ''; // track the last core type in the return, because it's endslice point will differ var lastCoreTypeFound = false; for (var i = len; i > 0; i--) { for (var j = 0; j < presentCoreTypes.length; j++) { // yeah i-1, take that away and there will be hell to pay! if (linesOfText[i-1].indexOf("["+presentCoreTypes[j]+"]") != -1 && !lastCoreTypeFound) { lastCoreType = presentCoreTypes[j]; lastCoreTypeFound = true; } } } if (!lastCoreTypeFound) { _level0.showMsg("parseHACPReturn() failed --> could not determine the last core type in the return"); return; } else { _level0.showMsg("parseHACPReturn() says --> the last core type in the return is: "+lastCoreType); } // END: BUGFIX 11/22/05 -Ap if (coreType == lastCoreType) { // the last core type is special because it has no [core..] tag below it endSlice = len; } else { endSlice = coreTypes[validCoreType+1]; // to be transformed into a number below } // get the startSlice and endSlice index numbers for cutting out the desiredChunk for (var i = 0; i < len; i++) { if (linesOfText[i].indexOf(coreType) != -1 && !startSliceFound) { // this should always prove to be true at some time during the loop, because of the error handling above startSlice = i+1; // we hit the desired core tag so the vars we want are 1 line below that startSliceFound = true; } if (linesOfText[i].indexOf(endSlice) != -1 && !endSliceFound && endSlice != len) { endSlice = i-1; // drops the [core_...] tag off the string endSliceFound = true; } } // get the desired chunk using the startSlice and endSlice, put it in a 2D array for (var i = startSlice; i <= endSlice; i++) { nameValuePairs.push(origLinesOfText[i].split("=")); } // add names value pairs to an object from the 2D array for (var i = 0; i < nameValuePairs.length; i++) { // index 0 is the varName index 1 is the value dataObj[nameValuePairs[i][0]] = nameValuePairs[i][1]; } // set _level0 vars to their proper values _level0.sendCommand = 0; checkForData(new Array("_level0.sendCommand"), "JAVASCRIPT", "putparam"); setDataHolderVars(dataObj); } // used by parseHACPReturn() function setDataHolderVars(obj) { for (var i in obj) { dataHolder[i] = obj[i]; showMsg("setDataHolderVars() --> value of dataHolder."+i+" = " +dataHolder[i]); } showMsg("setDataHolderVars() --> suspendData before the getparam is done = " + dataholder.suspendDataStr); fscommand("setcmReady"); } function onDataReceived (action) { showMsg("onDataReceived() callback has been triggered with an action of: "+action); if (action == "getparam") { checkForData(new Array("_level0.dataHolder.error"), "JAVASCRIPT", "parse"); getAICCData(); } else if (action == "parse") { // BEGIN: error handling if (useErrorHandling) { var errorCode = errObj.getErrorCode(); var errorText = errObj.getErrorText(); if (errorCode != 0) { if (errorCode == -101) { fscommand("errorMessage", "-101|undefined HACP error code or error text|INTERNAL ERROR: "); return; } else { fscommand("errorMessage", errorCode + "|" + errorText + "|" + "HACP RETURN ERROR: "); return; } } } // END: error handling parseHACPReturn(_level0.dataHolder.error, "core"); parseHACPReturn(_level0.dataHolder.error, "core_lesson"); } else if (action == "putparam") { checkForData(new Array("_level0.dataHolder.error"), "JAVASCRIPT", "clearparam"); sendAICCData(); }else if (action == "clearparam"){ // BEGIN: error handling if (useErrorHandling) { var errorCode = errObj.getErrorCode(); var errorText = errObj.getErrorText(); if (errorCode != 0) { if (errorCode == -101) { fscommand("errorMessage", "-101|undefined HACP error code or error text|INTERNAL ERROR: "); return; } else { fscommand("errorMessage", errorCode + "|" + errorText + "|" + "HACP RETURN ERROR: "); return; } } } // END: error handling if (_level0.exitAU == 1) { showMsg("onDataReceived() --> return received from from the LMS as a result of the exitAU command being sent"); } _level0.dataHolder.error = ""; checkForData(new Array("_level0.sendCommand"), "JAVASCRIPT", "putparam"); fscommand("setcmReady"); } else { showMsg("onDataReceived() failed --> Action received ("+action+") in not a valid one"); } } function setScroll() { this.output.scroll = this.output.maxscroll; } // output control function showMsg(msg, alternateField) { if (!alternateField) { this.output += msg+"\n"; } else { alternateField += msg+"\n"; } setScroll(); } function resetMsg() { this.output = ""; }