// Copyright 1998,1999 Macromedia, Inc. All rights reserved.// Localization stringsvar TRACK_system_not_found = "Tracking system not found.";//Constructs an Interactionfunction MM_interaction(theSelf,               theJudgeOnSel, theAllowMultiSel, theAllThatApply, theUnknownIsCorrect,               theDisabled, theTriesLimit, theTimeLimit,               theTrackIntId, theTrackObjectiveId,               theTrackQType,theTrackWeight, theKTrack) {  // properties  this.judgeOnSel = theJudgeOnSel;  this.allowMultiSel = theAllowMultiSel;  this.allThatApply = theAllThatApply;  this.unknownIsCorrect = theUnknownIsCorrect;  this.disabled = theDisabled;  this.tries = 0;  this.triesLimit = (theTriesLimit)?theTriesLimit:0;  this.triesAtLimit = false;  this.time = 0;  this.timeLeft = 0;  this.timeLimit = (theTimeLimit)?theTimeLimit:0;  this.timeAtLimit = false;  this.trackIntId = theTrackIntId;  this.trackObjectiveId = theTrackObjectiveId;  this.trackQType = theTrackQType;  this.trackWeight = theTrackWeight;  this.knowledgeTrack = theKTrack;  this.totalElems = 0;  this.possCorrect = 0;  this.possIncorrect = 0;  this.knownResponse = false;  this.totalCorrect = 0;  this.totalIncorrect = 0;  this.correct = false;  this.score = 0;  this._self = theSelf;  this._timeStart = 0;  this._timerID = 0;    this.browserIsNS = (navigator.appName.indexOf('Netscape') != -1);  this.browserIsIE = (navigator.appName.indexOf('Microsoft') != -1);  this.osIsWindows = (navigator.appVersion.indexOf('Win') != -1);  this.osIsMac = (navigator.appVersion.indexOf('Mac') != -1); // ????  this.browserVersion = parseFloat(navigator.appVersion);    this.e = new Array();  this.b = new Array();  // methods  this.init = MM_intInit;  this.reset = MM_intReset;  this.resetElems = MM_intResetElems;  this.enable = MM_intEnable;  this.disable = MM_intDisable;  this.setDisabled = MM_intSetDisabled;  this.update = MM_intUpdate;  this.add = MM_intAdd;  this.setTries = MM_intSetTries;  this.setTriesLimit = MM_intSetTriesLimit;  this.setTime = MM_intSetTime;  this.setTimeLimit = MM_intSetTimeLimit;  this.track = MM_intTrack  this.getTime = MM_intGetTime;  this.am = MM_intAm;  this.judge = MM_intJudge;  this.resetActionMgr = MM_intResetActionMgr;  this.setSegmNode = MM_intSetSegmNode;  this.getSegmNode = MM_intGetSegmNode;  this.setSegmDisabled = MM_intSetSegmDisabled;  this.getSegmDisabled = MM_intGetSegmDisabled;}//Calls the element init funtions if they exist, and then does a resetfunction MM_intInit() {  var i,j,localPC;  with (this) {    // init elems, and set totalElems, possCorrect, possIncorrect;    totalElems = 0;    possCorrect = 0;    possIncorrect = 0;    for (i in e) if (i != 'length') {      if (e[i].init != null) e[i].init();      totalElems++;      localPC = 0;      for (j in e[i].c) if (j != 'length' && e[i].c[j].isCorrect != null)        (e[i].c[j].isCorrect) ? localPC++ : possIncorrect++;      if (e[i]._singleChoice != null && localPC > 1)        localPC = 1;      possCorrect += localPC;    }    reset();    if (knowledgeTrack) {      var frm = findcmiframe(null);      if (frm == null) {        installcmi(window); //layers in NS        if (!CMIIsPresent()) {          var cmi = cmiinit(window);          if (cmi) CMIInitialize();          else if (!window.trackwarning) {            alert(TRACK_system_not_found);            window.trackwarning = true;      } } }       else {        if (window.CMIInitialize == null) frm.installcmi(window);        if (window.CMIInitialize != null) CMIInitialize();        if (!CMIIsPresent() && !window.trackwarnings) {          alert(TRACK_system_not_found);          window.trackwarning = true;  } } } }  window["'"+this._self+"'"] = this._self; //redeclare global on window in case inserted in layer}//Called to reset the interactionfunction MM_intReset() {  with (this) {    tries = 0;    triesAtLimit = false;    _timeStart = Math.floor((new Date()).getTime()/1000);    if (_timerID) clearTimeout(_timerID);    if (!disabled && timeLimit) _timerID = setTimeout(_self+".judge()",(timeLimit+1)*1000);    time = 0;    timeLeft = timeLimit;    timeAtLimit = false;      resetActionMgr();    resetElems();    update(true);  }}//Calls the reset for the individual elementsfunction MM_intResetElems() {  with (this) {    for (var i in e) if (i != 'length')      if (e[i].reset != null)  e[i].reset();    update(true);  }}//Enables the interactionfunction MM_intEnable() {  if (this.disabled) with (this) {    _timeStart = Math.floor((new Date()).getTime()/1000) - time;    if (timeLimit)      _timerID = setTimeout(_self+".judge()",Math.max(0,(timeLimit-time)+1)*1000);    disabled = false;    update(true);    for (var i in e) if (i != 'length')      if (e[i].enable != null)  e[i].enable();  }}//Disables the interactionfunction MM_intDisable() {  if (!this.disabled) with (this) {    update(true);  // update 'time'    if (_timerID) clearTimeout(_timerID);  // clear the timer    disabled = true;    for (var i in e) if (i != 'length')      if (e[i].disable != null)  e[i].disable();  }}//Calls the approppriate disable or enable functionfunction MM_intSetDisabled(theDisabled) {  if (theDisabled) this.disable();  else this.enable();}//Update the interaction state// Note: tries will be updated by the judge method, and time will//       be updated by both this method and the judge method.function MM_intUpdate(noJudge) {  if (!this.disabled) with (this) {    knownResponse = false;    totalCorrect = 0;    totalIncorrect = 0;    correct = false;    score = 0;    for (var i in e) if (i != 'length') {      for (var j in e[i].c) if (j != 'length') {        if (e[i].c[j].selected) {          knownResponse = true;          score += e[i].c[j].score;          if (e[i].c[j].isCorrect != null)            (e[i].c[j].isCorrect) ? totalCorrect++ : totalIncorrect++;    } } }    if (!knownResponse) correct = unknownIsCorrect;    else if (totalIncorrect != 0) correct = false;    else if (totalCorrect == 0) correct = null; // not judged    else correct = (!allThatApply || totalCorrect >= possCorrect);      time = Math.floor((new Date()).getTime()/1000) - _timeStart;    if (timeLimit && !timeAtLimit) {      timeLeft = Math.max(0, timeLimit - time);      timeAtLimit = (time > timeLimit);    }      if (judgeOnSel && !noJudge)  judge();  }}function MM_intSetTries(theTries) {  with (this) {    tries = theTries;    triesAtLimit = (triesLimit) ? (tries >= triesLimit) : false;  }}function MM_intSetTriesLimit(theTriesLimit) {  with (this) {    triesLimit = theTriesLimit;    triesAtLimit = (triesLimit) ? (tries >= triesLimit) : false;  }}function MM_intSetTime(theTime) {  with (this) {    time = Math.max(0, theTime);    _timeStart = Math.floor((new Date()).getTime()/1000) - time;    timeLeft = (timeLimit) ? Math.max(0, timeLimit - time) : timeLimit;    timeAtLimit = (timeLimit) ? (time > timeLimit) : false;    if (_timerID) clearTimeout(_timerID);  // clear the timer    if (!disabled && timeLimit)      _timerID = setTimeout(_self+".judge()",Math.max(0,(timeLimit-time)+1)*1000);  }}function MM_intSetTimeLimit(theTimeLimit) {  with (this) {    if (!disabled)      time = Math.floor((new Date()).getTime()/1000) - _timeStart;    timeLimit = theTimeLimit;    timeLeft = (timeLimit) ? Math.max(0, timeLimit - time) : timeLimit;    timeAtLimit = (timeLimit) ? (time > timeLimit) : false;    if (_timerID) clearTimeout(_timerID);  // clear the timer    if (!disabled && timeLimit)      _timerID = setTimeout(_self+".judge()",Math.max(0,(timeLimit-time)+1)*1000);  }}function MM_intAdd(theType, A, B, C, D, E, F, G, H, I, J, K, L, M) {  var theObj = eval("new MM_" + theType + "(" + this._self + ", A, B, C, D, E, F, G, H, I, J, K, L, M)");  if (theObj._isChoice != null)    this.e[A].c[B] = theObj;  else    this.e[A] = theObj;}function MM_intTrack() {  var  aDt= new Date();  var curHr=aDt.getHours()+'', curMin=aDt.getMinutes()+'', curSec=aDt.getSeconds()+'';  var curDay=aDt.getDate()+'', curMonth=aDt.getMonth()+1+'', curYear=aDt.getYear(), dmy;  var lat = Math.floor(aDt.getTime()/1000) - this._timeStart;  var x=3600;  var y=60;  var hrs=Math.round(lat/x - lat%x/x)+'';  var min=Math.round((lat-hrs*x)/y-(lat-hrs*x)%y/y)+'';  var sec=Math.round(lat-hrs*x-min*y)+'';  var sRes,cRes,res,aName,bName,isC,isNC,isSel,iType;  if (curYear < 1900) curYear += 1900;  if (curDay.toString().length==1) curDay = '0'+curDay;  if (curMonth.toString().length==1) curMonth = '0'+curMonth;  dmy = curDay+"/"+curMonth+"/"+curYear;    sRes=cRes=res=aName=bName=""  with (this) {      if (trackQType.length==0) return;    iType=trackQType.charAt(0).toLowerCase();    if (allThatApply&&possCorrect>1) sRes=cRes='{';        for (var i in e) if (i != 'length') {      for (var j in e[i].c) if (j != 'length') {        isC=e[i].c[j].isCorrect;        isSel=e[i].c[j].selected;        if (iType=='m') {          aName=e[i].c[j]._elem._name;          bName=e[i].c[j]._target._name;          if (isC) cRes+=aName+'.'+bName+',';          if (isSel) sRes+=aName+'.'+bName+',';        }        else if (iType=='f') {          aName=e[i].value;          bName=MM_textDeencrypt(e[i].c[j].expectedValue);          if (isC) cRes+=bName+',';          if (isSel) sRes+=aName+',';        }        else if ((iType=='c')||(iType=='t')) {          if (e[i]._trkObj!=null) {            aName=e[i].c[j].expectedValue;            x=aName.indexOf(':');            aName=aName.substring(0,x)+'-'+aName.substring(x+1,aName.length)            bName=e[i].value          }          else if (e[i]._tick!=null) {            aName=e[i].c[j].expectedValue;            if (isSel) bName = aName;          }          else if (e[i]._stateMask!=null && totalElems==1) {            aName=e[i].expectedValue;            bName=e[i].value;          }          else            aName=bName=e[i].c[j]._name;          if (isC) cRes+=aName+',';          if (isSel) sRes+=bName+',';        }        else {          aName=bName='';          if (isC) cRes+=',';          if (isSel) sRes+=',';        }        isNC=(isC==false)&&isSel;        isC=isC&&isSel;        if (possCorrect>1)  res=res+(isC?'c,':isNC?'w,':isSel?'n,':'');        else if (isSel) res = isC?'c':isNC?'w':'n';      }    }        if (sRes.charAt(sRes.length-1)==',') sRes=sRes.substring(0,sRes.length-1);    if (cRes.charAt(cRes.length-1)==',') cRes=cRes.substring(0,cRes.length-1);    if (res.charAt(res.length-1)==',') res=res.substring(0,res.length-1);    if (allThatApply&&possCorrect>1) {      sRes=sRes+'}';      cRes=cRes+'}';    }    if (window.CMIIsPresent && CMIIsPresent()) {      if (hrs.toString().length==1) hrs = '0'+hrs;      if (min.toString().length==1) min = '0'+min;      if (sec.toString().length==1) sec = '0'+sec;      if (curHr.toString().length==1) curHr = '0'+curHr;      if (curMin.toString().length==1) curMin = '0'+curMin;      if (curSec.toString().length==1) curSec = '0'+curSec;      CMIAddInteraction(dmy, curHr+":"+curMin+":"+curSec,        trackIntId, trackObjectiveId, trackQType,        cRes, sRes, res, trackWeight, hrs+":"+min+":"+sec);    }  }  }function MM_intGetTime() {   var date = new Date();  this.time = (date.getTime()/1000 - this._timeStart)*1000;  return this.time/1000;}//Finds any object in either browser using recursion.//Only pass the first argument, the name of the object to find.//Returns a pointer the object if found, else an empty string.//  MM_intFindObject('bar') returns the object//  document.layers['foo'].document.layers['bar']function MM_intFindObject(objName,  parentObj) {  var i,tempObj="",found=false,curObj = "";  var NS = (navigator.appName.indexOf("Netscape") != -1);  if (!NS && document.all) curObj = document.all[objName]; //IE4  if (!curObj) {    parentObj = (parentObj != null)? parentObj.document : document;    if (parentObj[objName] != null) curObj = parentObj[objName]; //at top level    else { //if in form      if (parentObj.forms) for (i=0; i<parentObj.forms.length; i++) {  //search level for form object        if (parentObj.forms[i][objName]) {          curObj = parentObj.forms[i][objName];          found = true; break;      } }      if (!found && NS && parentObj.layers && parentObj.layers.length > 0) {        parentObj = parentObj.layers;        for (i=0; i<parentObj.length; i++) { //else search for child layers          tempObj = MM_intFindObject(objName,parentObj[i]); //recurse          if (tempObj) { curObj = tempObj; break;} //if found, done  } } } }  return curObj;}//Called from within conditions to check document propertiesfunction MM_getDocProp(theName, theProp, theType) {  var theObj = MM_intFindObject(theName);  if (theObj) return eval('theObj.' + theProp);  else return null;}//*********  ACTION MGR METHODS  *********function MM_intJudge(treeRoot,curRoot,level) {  var i=0,theNode,retVal=true,firstCond = true;  level = (curRoot == null)?0:level+1;  if (!level) {    curRoot = this; //set tree to highest level    if (this.disabled) retVal=false;    else {      this.time = Math.floor((new Date()).getTime()/1000) - this._timeStart;      if (this.timeLimit && !this.timeAtLimit) {        this.timeLeft = Math.max(0, this.timeLimit - this.time);        this.timeAtLimit = (this.time > this.timeLimit);      }      this.tries++;      if (this.triesLimit)        this.triesAtLimit = (this.tries >= this.triesLimit);  } } else if (treeRoot.curNode != null && curRoot == treeRoot.curNode) //if at curNode    i = treeRoot.curIndex;  //offset by index  for (i; (retVal && i<curRoot.b.length); i++) {    theNode = curRoot.b[i];    if (this.disabled) retVal=false;    else if (theNode.disabled) continue;    else if (theNode.type == "segm") { //SEGMENT      curNode = (theNode.curNode)?theNode.curNode:theNode;      if (curNode != 'done')        retVal = MM_intJudge(theNode,curNode,level);   //start from that node      else if (!level) continue;    } else if (theNode.type == 'cond') { //CONDITION      if (eval(theNode.data)) {        if (!treeRoot.data) treeRoot.curNode = 'done';  //if not "auto-reset tree", set curNode        retVal = MM_intJudge(treeRoot,theNode,level);        if (level) break;      } else if (firstCond) {        firstCond = false;        if (!treeRoot.data) {treeRoot.curNode = curRoot;  treeRoot.curIndex = i;}      }    } else if (theNode.type == 'actn') { //ACTION      if (!treeRoot.data) //not auto-reset        if (i<(curRoot.b.length-1)) { //not last node          treeRoot.curNode = curRoot;  treeRoot.curIndex = i+1; //set curNode to next node        } else treeRoot.curNode = 'done'; //last node, clear curNode      if (theNode.data == 'stop') retVal=false; //STOP      else eval(theNode.data);  } }  if (!level && curRoot!=null && curRoot.knowledgeTrack) curRoot.track();  return retVal}//Disables or enables ActionMgr segments. If no segment passed,//disables *all* segments. Returns false if segment not found.function MM_intSetSegmDisabled(segmName,disable) {  var i, retVal=false;  for (i=0; i<this.b.length; i++) //search for segment    if (!segmName || this.b[i].name==segmName) {      this.b[i].disabled=disable; retVal = true;      if (segmName) break;    }  return retVal}//Returns the disabled flag from an ActionMgr segment.//Returns null if segment not found.function MM_intGetSegmDisabled(segmName) {  var i, retVal=null;  for (i=0; i<this.b.length; i++) //search for segment    if (this.b[i].name==segmName) {      retVal = this.b[i].disabled; break;    }  return retVal}function MM_intResetActionMgr(segmName) {  var i;  if (segmName != null) MM_intTreeSetCurNode(segmName,null,this); //clear single curNode  else for (i=0;i<this.b.length;i++) this.b[i].curNode = null; //clear all curNodes}function MM_intSetSegmNode(segmName,condName) {  var i, curRoot=null;  if (!condName) this.resetActionMgr(segmName);  else {    for (i=0; i<this.b.length; i++) //search for segment, set as curRoot      if (this.b[i].name == segmName) { curRoot = this.b[i]; break; }    MM_intTreeSetCurNode(condName,null,curRoot,curRoot);  }}function MM_intTreeSetCurNode(nodeName,newVal,treeRoot,curRoot) {  var i,theNode;  if (curRoot==null) curRoot = treeRoot; //if first time, use treeRoot  for (i=0; i<curRoot.b.length; i++) {    theNode = curRoot.b[i];    if (theNode.type == "segm") { //SEGMENT      if (theNode.name == nodeName) theNode.curNode  = newVal;      else MM_intTreeSetCurNode(nodeName,newVal,theNode,theNode);    } else if (theNode.type == 'cond') { //CONDITION      if (theNode.name == nodeName) {  //if name found        treeRoot.curNode = curRoot;  treeRoot.curIndex = i;        break;      } else MM_intTreeSetCurNode(nodeName,newVal,treeRoot,theNode);  } }}//Returns the current node for the given Segment, returned as:// top of segment    - "" (empty string)// middle of segment - condition name// end of segment    - "done"function MM_intGetSegmNode(segmName) {  var i, curNode='';  for (i=0; i<this.b.length; i++) //search for segment    if (this.b[i].name == segmName) {       curNode = this.b[i].curNode;      if (curNode==null) curNode = "";      else if (curNode!="done") curNode = curNode.b[this.b[i].curIndex].name;      break;     }  return curNode}//*********  ACTION MGR NODE CLASS  *********function MM_intNode(theType,theName,theData) {  this.type = (theType)?theType:'';  this.name = (theName)?theName:'';  this.data = (theData)?theData:'';  this.b = new Array();}//Create Action Manager (tree)function MM_intAm(theType,theName,theData) {  if (theType == "segm") {      if (!this.tParent) { //initialize system        this.tParent = new Array(); //tree parent nodes        this.tIndex = new Array();  //child indexes        this.tIndex[0] = -1;        //set index for root depth      }      this.tLevel = 0;            //reset level to 0      this.tIndex[this.tLevel]++; //increment the index      this.b[this.tIndex[this.tLevel]] = new MM_intNode("segm", theName,theData); //create tree      this.tParent[this.tLevel] = this.b[this.tIndex[this.tLevel]]; //put this tree root at top level      this.tIndex[this.tLevel+1] = -1;                              //reset child level index  } else if (theType == "actn") {     var parentNode = this.tParent[this.tLevel];    //get parent     var levelIndex = ++this.tIndex[this.tLevel+1]; //get index     parentNode.b[levelIndex] = new MM_intNode('actn',theName,theData); //add action  } else if (theType == "cond") {     var parentNode = this.tParent[this.tLevel];    //get parent     var levelIndex = ++this.tIndex[this.tLevel+1]; //get index     parentNode.b[levelIndex] = new MM_intNode('cond',theName,theData); //add condition     this.tLevel++; //go down a level     this.tParent[this.tLevel] = parentNode.b[levelIndex]; //save this node as parent     this.tIndex[this.tLevel+1] = -1;                      //reset child level index  } else if (theType == "end") {     this.tLevel--;  //go up a level  }}
