﻿$TTFlash mit SCORM 2004-Verfolgung
$DS
Veröffentlichungsvorlage für SCORM 2004-Kommunikation. Wurde speziell zur Unterstützung von Lern-Interaktionen modifiziert.  Mit integriertem JavaScript kann ein ADL API-Objekt für SCORM 2004 gesucht und initialisiert werden, und mit dem FSCommand 'glue' lassen sich LMS-Funktionen von Flash aus aufrufen.

$DF

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de">
<head>
$CS
<script type="text/javascript" language="JavaScript" name="fsIeVbscript">
<!--
// Hook für Internet Explorer
if (navigator.appName && navigator.appName.indexOf("Microsoft") != -1 && navigator.userAgent.indexOf("Windows") != -1 && navigator.userAgent.indexOf("Windows 3.1") == -1) {
	document.write('<script language=\"VBScript\"\>\n');
	document.write('On Error Resume Next\n');
	document.write('Sub $TI_FSCommand(ByVal command, ByVal args)\n');
	document.write('	Call $TI_DoFSCommand(command, args)\n');
	document.write('End Sub\n');
	document.write('</script\>\n');
}
//-->
</script>
<title>$TI</title>
</head>
<script type="text/javascript" language="JavaScript" name="cmifrag">
<!--

// FS SCORM - FSCommand-Adapter für ADL SCORM 2004 und Flash MX 2004-Lerninteraktionen
// Version 1.0    12/10/04
// Geändert von Andrew Chemey, Macromedia
// Basiert auf FS SCORM-Adapter Version 1.2.4:
// 		Teile Copyright 2002 Pathlore Software Corporation. Alle Rechte vorbehalten.
// 		Teile Copyright 2002 Macromedia Inc. Alle Rechte vorbehalten.
// 		Teile Copyright 2003 Click2learn Inc. Alle Rechte vorbehalten.
// 		Entwickelt von Tom King, Macromedia, Leonard Greenberg, Pathlore, und Claude Ostyn, Click2learn, Inc.
// 		Enthält Code von Jeff Burton und Andrew Chemey, Macromedia (09.01.02)
// -----------------------------------------------------------------

// Ändern Sie diese vorgegebenen Werte je nach Bedarf und Belieben.
// Richtung bei der Suche nach API-Objekten (0 - von unten nach oben; 1 - von oben nach unten)
var g_intAPIOrder = 1;
var g_bShowApiErrors = false; 	// Ändern Sie dies auf "true", um Fehlermeldungen anzuzeigen

var g_bInitializeOnLoad = true; // Ändern Sie dies auf "false", damit LMS beim Laden der HTML-Seite nicht initialisiert wird

// Übersetzen Sie diese Strings, wenn g_bShowApiErrors "true" ist und Sie die Anwendung lokalisieren müssen
var g_strAPINotFound = "Management system interface not found.";
var g_strAPITooDeep = "Cannot find API - too deeply nested.";
var g_strAPIInitFailed = "Found API but LMSInitialize failed.";
var g_strAPISetError = "Trying to set value but API not available.";
var g_strFSAPIError = 'LMS API adapter returned error code: "%1"\nWhen FScommand called API.%2\nwith "%3"';
var g_strDisableErrorMsgs = "Select cancel to disable future warnings.";

// Ändern Sie g_bSetCompletedAutomatically auf 'true', wenn der Status beim Aufruf von LMSFinish automatisch auf "completed" gesetzt werden soll. 
// Normalerweise bleibt dieses Flag "false", wenn der Flash-Film selbst den Status auf "completed" setzt, indem ein FSCommand gesendet wird, der den Status auf "completed", "passed" oder "failed" (die beide "completed" implizieren) setzt. "passed" or "failed" (both of which imply "completed")"
var g_bSetCompletedAutomatically = false;

// Dieser Wert wird normalerweise vom LMS angegeben, in diesem Fall jedoch nicht. Dies ist der Standardwert, mit dem festgestellt wird, ob der Status "passed" oder "failed" ist.
// Setzen Sie dies auf "null", wenn das Flash-Actionscript anhand seiner eigenen Methode feststellt, ob der Status "passed" oder "failed" ist; andernfalls setzen Sie dies auf einen Wert von 0 bis 1 inklusive (kann Gleitkommawert sein, z.B."0,75".
var g_SCO_MasteryScore = null; // erlaubte Werte: 0,0..1,0 oder "null"

//==================================================================

// WARNUNG!!!
// Nehmen Sie unterhalb dieser Zeile nur Änderungen vor, wenn Sie genau wissen, was Sie tun!

// Sie sollten diese beiden Werte nicht ändern müssen, da die Vorgaben der Flash-Vorlage darauf basieren.
var g_nSCO_ScoreMin = 0; 		// muss eine Zahl sein
var g_nSCO_ScoreMax = 100; 		// muss eine Zahl > nSCO_Score_Min sein

// Laut SCORM-Angaben überschreibt der vom LMS bereitgestellte LMS-Mastery-Wert, falls vorhanden, SCO bei der Interpretation, ob der Wert interpretiert werden soll, wenn der Status für 'erfolgreich' oder 'fehlgeschlagen' bestimmt wird.
// Die Vorlage versucht, den Mastery-Wert zu erhalten und, falls dieser verfügbar ist, den Status auf 'erfolgreich' oder 'fehlgeschlagen' zu setzen, wenn von SCO ein Wert gesendet wird.
// Dies kann erst vom LMS bestimmt werden, wenn SCO abgeschlossen wurde.
// Der Standardwert für dieses Flag lautet 'true'. Setzen Sie den Wert auf 'false', wenn Sie nicht vorhersagen möchten, wie der Status für 'erfolgreich' und 'fehlgeschlagen' auf der Grundlage des Mastery-Werts vom LMS festgelegt wird (LMS wird letztendlich ohnehin gewinnen).
var g_bInterpretMasteryScore = true;

// Dieses Skript implementiert verschiedene Aspekte des allgemeinen Logikverhaltens einer SCO.

/////////// API-SCHNITTSTELLENINITIALISIERUNG UND AUFFANGFUNKTIONEN ////////
var g_nFindAPITries = 0;
var g_objAPI = null;
var g_bInitDone = false;
var g_bFinishDone = false;
var	g_bSCOBrowse = false;
var g_dtmInitialized = new Date(); // Wird nach der Initialisierung angepasst.
var g_bMasteryScoreInitialized = false;

var g_varInterval = "";			// globales Intervall
var g_intIntervalSecs = 3 		// Anzahl der Sekunden, die auf das Laden der SCORM-API gewartet wird
var g_intPollSecs = 0.25			// Die für das Abfragen der API angegebene Anzahl von Sekunden
var g_intCurrentTime = new Date().getTime();
var g_intAPI = 0;				// Zu suchender API-Typ; zulässige Werte: 0 - SCORM 2004; 1 - SCORM 1.2 (oder 1.1)
var g_aryAPI = ["1.0", "0.2"]	// Array, das die API-Versionen speichert
var g_strAPIVersion = -1;

function AlertUserOfAPIError(strText) {
	if (g_bShowApiErrors) {
		var s = strText + "\n\n" + g_strDisableErrorMsgs;
		if (!confirm(s)){
			g_bShowApiErrors = false
		}
	}
}

function ExpandString(s){
	var re = new RegExp("%","g")
	for (i = arguments.length-1; i > 0; i--){
		s2 = "%" + i;
		if (s.indexOf(s2) > -1){
			re.compile(s2,"g")
			s = s.replace(re, arguments[i]);
		}
	}
	return s
}

function findAPI(win)
{
	// Fensterhierarchie nach einem Objekt namens "API_1484_11" (für SCORM 2004) oder "API" (für SCORM 1.2 oder älter) durchsuchen
	// Aktuelles Fenster (win) durchsuchen und rekursiv in allen untergeordneten Bildern suchen
	if(g_intAPI == 0)
	{
		if(win.API_1484_11 != null)
		{
			return win.API_1484_11;
		}
	} else if(g_intAPI == 1 || g_intAPI == "") {
		if (win.API != null)
		{
			g_strAPIVersion = g_aryAPI[g_intAPI];
			return win.API;
		}
	}

	if (win.length > 0)  // Bilder prüfen
	{
		for (var i=0;i<win.length;i++)
		{
			var objAPI = findAPI(win.frames[i]);
			if (objAPI != null)
			{
				return objAPI;
			}
		}
	}
	return null;
}


function getAPI(intAPISearchOrder)
{
	// intAPISearchOrder ist 0 - bei aktuellem Fenster beginnen und nach oben bewegen; 1 - bei oberstem Fenster beginnen und nach unten bewegen.
	var objAPI = null;
	intAPISearchOrder=((typeof(intAPISearchOrder)=='undefined')?0:intAPISearchOrder);
	if(intAPISearchOrder==0)
	{
		// bei aktuellem Fenster beginnen und übergeordnete Fenster/Bilder rekursiv durchsuchen
		objAPI = findAPI(window);
		if((objAPI==null) && (window.opener != null) && (typeof(window.opener) != "undefined"))
		{
			objAPI = findAPI(window.opener);
		} else if((objAPI==null) && (window.parent != null) && (typeof(window.parent) != "undefined")) {
			objAPI = findAPI(window.parent);
		}
		if((objAPI==null) && (g_intAPI < (g_aryAPI.length-1)))
		{
			g_intAPI++;
			objAPI = getAPI(intAPISearchOrder);
		}
	} else {
		// bei oberstem Fenster beginnen und untergeordnete Bilder rekursiv durchsuchen
		objAPI = findAPI(this.top);

		if (objAPI == null)
		{
			// Die API wurde in der Hierarchie des aktuellen Fensters nicht gefunden. Wenn das aktuelle Fenster von einem anderen Fenster geöffnet wurde ('Fensteröffner'), prüfen Sie die Hierarchie dieses anderen Fensters.
			objTopWindow=window.top;

			objTopWindow = objTopWindow.opener;

			while (objTopWindow && !objAPI)
			{
				//Fensteröffner wird geprüft
				objAPI = findAPI(objTopWindow.top);
				if (objAPI==null) objTopWindow = objTopWindow.opener;
			}
			if(objAPI==null && g_intAPI < (g_aryAPI.length-1))
			{
				g_intAPI++;
				objAPI = getAPI(intAPISearchOrder);
			}
		}
	}
	if(objAPI==null)
	{
		// API nicht gefunden
	} else if(objAPI != null && g_strAPIVersion == -1) {
		g_strAPIVersion = objAPI.version;
	}

	return objAPI;
}

function waitForAPI()
{
	if(new Date().getTime() > (g_intCurrentTime + g_intIntervalSecs*1000) || APIOK())
	{
		// Zeit überschritten oder API gefunden
		clearInterval(g_varInterval);
		if(!APIOK())
		{
			g_objAPI = null;
		} else {
			if (g_bInitializeOnLoad) {
				SCOInitialize()
			}
		}
	} else {
		g_objAPI = getAPI(g_intAPIOrder);
	}
}

function APIOK() {
	return ((typeof(g_objAPI)!= "undefined") && (g_objAPI != null))
}

function SCOInitialize() {
	var err = true;
	if (!g_bInitDone) {
		if (!APIOK()) {
			AlertUserOfAPIError(g_strAPINotFound);
			err = false
		} else {
			err = g_objAPI.Initialize("");
			if (err == "true") {
				g_bSCOBrowse = (g_objAPI.GetValue("cmi.mode") == "browse");
				if (!g_bSCOBrowse) {
					if (g_objAPI.GetValue("cmi.completion_status") == "not attempted") {
						err = g_objAPI.SetValue("cmi.completion_status","incomplete")
					}
				}
			} else {
				AlertUserOfAPIError(g_strAPIInitFailed)
			}
		}
		if (typeof(SCOInitData) != "undefined") {
			// Die SCOInitData-Funktion kann in einem anderen Skript der SCO definiert werden
			SCOInitData()
		}
		g_dtmInitialized = new Date();
	}
	g_bInitDone = true;
	return (err + "") // String als Typ erzwingen
}

function SCOFinish() {
	if ((APIOK()) && (g_bFinishDone == false)) {
		SCOReportSessionTime()
		if (g_bSetCompletedAutomatically){
			SCOSetStatusCompleted();
		}
		if (typeof(SCOSaveData) != "undefined"){
			// Die SCOSaveData-Funktion kann in einem anderen Skript von SCO definiert werden
			SCOSaveData();
		}
		g_bFinishDone = (g_objAPI.Terminate("") == "true");
	}
	return (g_bFinishDone + "" ) // String als Typ erzwingen
}

// Rufen Sie diese Auffangfunktionen auf, anstatt einen direkten Aufruf an den API-Adapter zu versuchen.
function SCOGetValue(nam)			{return ((APIOK())?g_objAPI.GetValue(nam.toString()):"")}
function SCOCommit()					{return ((APIOK())?g_objAPI.Commit(""):"false")}
function SCOGetLastError()		{return ((APIOK())?g_objAPI.GetLastError():"-1")}
function SCOGetErrorString(n)	{return ((APIOK())?g_objAPI.GetErrorString(n):"No API")}
function SCOGetDiagnostic(p)	{return ((APIOK())?g_objAPI.GetDiagnostic(p):"No API")}

// LMSSetValue wird mit der komplexeren Datenmanagementlogik unten implementiert.

var g_bMinScoreAcquired = false;
var g_bMaxScoreAcquired = false;

// Spezielle Logik beginnt hier.
function SCOSetValue(nam,val){
	var err = "";
	if (!APIOK()){
			AlertUserOfAPIError(g_strAPISetError + "\n" + nam + "\n" + val);
			err = "false"
	} else if (nam == "cmi.score.raw") err = privReportRawScore(val)
	if (err == ""){
			err = g_objAPI.SetValue(nam,val.toString() + "");
			if (err != "true") return err
	}
	if (nam == "cmi.score.min"){
		g_bMinScoreAcquired = true;
		g_nSCO_ScoreMin = val
	}
	else if (nam == "cmi.score.max"){
		g_bMaxScoreAcquired = true;
		g_nSCO_ScoreMax = val
	}
	return err
}

function privReportRawScore(nRaw) { // Nur von SCOSetValue aufgerufen.
	if (isNaN(nRaw)) return "false";
	if (!g_bMinScoreAcquired){
		if (g_objAPI.SetValue("cmi.score.min",g_nSCO_ScoreMin+"")!= "true") return "false"
	}
	if (!g_bMaxScoreAcquired){
		if (g_objAPI.SetValue("cmi.score.max",g_nSCO_ScoreMax+"")!= "true") return "false"
	}
	if (g_objAPI.SetValue("cmi.score.raw", nRaw)!= "true") return "false";
	g_bMinScoreAcquired = false;
	g_bMaxScoreAcquired = false;
	if (!g_bMasteryScoreInitialized){
		var nTemp = SCOGetValue("cmi.scaled_passing_score");
		nTemp = (nTemp <= 0?0:nTemp * 100);
		var nMasteryScore = parseInt(nTemp,10);
		if (!isNaN(nMasteryScore)) g_SCO_MasteryScore = nMasteryScore
	}
  	if ((g_bInterpretMasteryScore)&&(!isNaN(g_SCO_MasteryScore))){
    	var stat = (nRaw >= g_SCO_MasteryScore? "passed" : "failed");
    	if (SCOSetValue("cmi.success_status",stat) != "true") return "false";
  	}
  	return "true"
}

function MillisecondsToCMIDuration(n) {
// Dauer von Millisekunden in Format 0000:00:00.00 konvertieren
	var hms = "";
	var dtm = new Date();	dtm.setTime(n);
	var h = "000" + Math.floor(n / 3600000);
	var m = "0" + dtm.getMinutes();
	var s = "0" + dtm.getSeconds();
	var cs = "0" + Math.round(dtm.getMilliseconds() / 10);
	hms = "PT" + h.substr(h.length-4)+"H"+m.substr(m.length-2)+"M";
	hms += s.substr(s.length-2)+"S";
	return hms
}

// SCOReportSessionTime wird von diesem Skript automatisch aufgerufen, Sie können es jedoch auch jederzeit von SCO aus aufrufen.
function SCOReportSessionTime() {
	var dtm = new Date();
	var n = dtm.getTime() - g_dtmInitialized.getTime();
	return SCOSetValue("cmi.session_time",MillisecondsToCMIDuration(n))
}

// Da nur der SCO-Designer weiß, was "completed" bedeutet, kann ein anderes SCO-Skript diese Funktion aufrufen, um den Status "completed" einzustellen.
// Die Funktion überprüft, ob sich SCO nicht im Modus "Durchsuchen" befindet, und vermeidet den Status "passed" oder "failed", da dadurch "completed" impliziert wird.
function SCOSetStatusCompleted(){
	var stat = SCOGetValue("cmi.completion_status");
	if (SCOGetValue("cmi.lesson_mode") != "browse"){
		if ((stat!="completed") && (stat != "passed") && (stat != "failed")){
			return SCOSetValue("cmi.completion_status","completed")
		}
	} else return "false"
}

// Zielmanagementlogik

function SCOSetObjectiveData(id, elem, v) {
	var result = "false";
	var i = SCOGetObjectiveIndex(id);
	if (isNaN(i)) {
		i = parseInt(SCOGetValue("cmi.objectives._count"));
		if (isNaN(i)) i = 0;
		if (SCOSetValue("cmi.objectives." + i + ".id", id) == "true"){
			result = SCOSetValue("cmi.objectives." + i + "." + elem, v)
		}
	} else {
		result = SCOSetValue("cmi.objectives." + i + "." + elem, v);
		if (result != "true") {
			// Möglicherweise werden vom LMS nur aufgezeichnete Einträge akzeptiert
			i = parseInt(SCOGetValue("cmi.objectives._count"));
			if (!isNaN(i)) {
				if (SCOSetValue("cmi.objectives." + i + ".id", id) == "true"){
					result = SCOSetValue("cmi.objectives." + i + "." + elem, v)
				}
			}
		}
	}
	return result
}

function SCOGetObjectiveData(id, elem) {
	var i = SCOGetObjectiveIndex(id);
	if (!isNaN(i)) {
		return SCOGetValue("cmi.objectives." + i + "."+elem)
	}
	return ""
}

function SCOGetObjectiveIndex(id){
	var i = -1;
	var nCount = parseInt(SCOGetValue("cmi.objectives._count"));
	if (!isNaN(nCount)) {
		for (i = nCount-1; i >= 0; i--){ //gehen Sie zurück, wenn LMS Aufzeichnungen durchführt
			if (SCOGetValue("cmi.objectives." + i + ".id") == id) {
				return i
			}
		}
	}
	return NaN
}

// Funktionen, die AICC-kompatible Token oder Abkürzungen in SCORM-Token konvertieren.
function AICCTokenToSCORMToken(strList,strTest){
	var a = strList.split(",");
	var c = strTest.substr(0,1).toLowerCase();
	for (i=0;i<a.length;i++){
			if (c == a[i].substr(0,1)) return a[i]
	}
	return strTest
}

function normalizeStatus(status){
	return AICCTokenToSCORMToken("completed,incomplete,not attempted,failed,passed", status)
}

function normalizeInteractionType(theType){
	return AICCTokenToSCORMToken("true-false,choice,fill-in,matching,performance,sequencing,likert,numeric", theType)
}

function normalizeInteractionResult(result){
	var strInteractionResult = AICCTokenToSCORMToken("correct,wrong,unanticipated,neutral", result)
	strInteractionResult = (strInteractionResult=="wrong"?"incorrect":strInteractionResult);
	return strInteractionResult;
}

function checkInteractionResponse(response_str)
{
	var result_str = "";
	for(var char_int=0;char_int<response_str.length;char_int++)
	{
		if(response_str.substr(char_int,1) == "." || response_str.substr(char_int,1) == ",")
		{
			if(response_str.substr(char_int - 1,1) != "[" && response_str.substr(char_int + 1,1) != "]")
			{
				result_str += "[" + response_str.substr(char_int,1) + "]";
			} else {
				result_str += response_str.substr(char_int,1);
			}
		} else {
			result_str += response_str.substr(char_int,1);
		}
	}
	result_str = (result_str==""?"0":result_str);
	return result_str;
}

function formatTimestamp(time_var)
{
	return formatDate() + "T" + formatTime(time_var, undefined, undefined, 2);
}


// ******************************************************************
// *
// *     Methode:           formatTime
// *     Beschreibung:      Formatiert Sekunden (als Parameter übergeben) in PTxHyMzS
// *     Rückgabewerte:          String (Zeit im Format HHHH:MM:SS)
// *
// ******************************************************************
function formatTime(time_var, minutes_str, seconds_str, typeFormat_int)
{
	var days_str, hours_str, formattedTime_str;
	days_str = "0";
	if(time_var == undefined)
	{
		// Zeit anhand aktueller Uhrzeit des heutigen Tages erstellen
		var time_obj = new Date();
		hours_str = time_obj.getHours();
		minutes_str = time_obj.getMinutes();
		seconds_str = time_obj.getSeconds();
	} else if(typeof(time_var) == "string" && time_var.indexOf(":") > -1) {
		var time_obj = time_var.split(":");
		hours_str = time_obj[0];
		minutes_str = time_obj[1];
		seconds_str = time_obj[2];
	} else {
		days_str    = "0";
		seconds_str = "0";
		minutes_str = "0";
		hours_str     = "0";

		seconds_str = Math.round(time_var);
		if(seconds_str > 59)
		{
			minutes_str = Math.round(seconds_str / 60);
			seconds_str = seconds_str - (minutes_str * 60);
		}
		if(minutes_str > 59)
		{
			hours_str = Math.round(minutes_str / 60);
			minutes_str = minutes_str - (hours_str * 60);
		}
		if(hours_str > 23)
		{
			days_str = Math.round(hours_str / 24);
			hours_str = hours_str - (days_str * 24);
		}
	}

	if(typeFormat_int == undefined || typeFormat_int == 1)
	{
		formattedTime_str = "P";

		if(days_str != "0")
		{
			formattedTime_str += days_str + "D";
		}
		formattedTime_str += "T" + hours_str + "H" + minutes_str + "M" + seconds_str + "S";
	} else {
		formattedTime_str = formatNum(hours_str, 2) + ":" + formatNum(minutes_str, 2) + ":" + formatNum(seconds_str, 2);
	}
	return formattedTime_str;
}

// ******************************************************************
// *
// *     Methode:           formatDate
// *     Beschreibung:      Formatiert Sekunden oder "MM/TT/JJJJ"
// *     Rückgabewerte:          String (Datum im Format "JJJJ-MM-TT")
// *
// ******************************************************************
function formatDate(date_var, day_str, year_str)
{
	if (date_var == undefined) {
		// Datum anhand des heutigen Datums erstellen
		var date_obj = new Date();
		date_var = formatNum((date_obj.getMonth()+1), 2);
		day_str  = formatNum((date_obj.getDate()), 2);
		year_str = (date_obj.getFullYear());
	} else if(typeof(date_var) == "string" && date_var.indexOf("/") > -1) {
		// Von MM/TT/JJJJ konvertieren
		var date_obj = date_var.split("/");
		date_var = formatNum(date_obj[0], 2);
		day_str  = formatNum(date_obj[1], 2);
		year_str = formatNum(date_obj[2], 4);
	}
	var formattedDate_str = (year_str + "-" + date_var + "-" + day_str);
	return formattedDate_str;
}

// ******************************************************************
// *
// *    Methode:         formatNum
// *    Beschreibung:     Konvertiert die an diese Funktion übergebene Zahl in einen mit Nullen aufgefüllten Wert. Dabei handelt es sich in der Regel um eine zwei- oder vierstellige Zahl (z. B. wird aus 2 die Zahl 02 oder 0002).
// *    Rückgabewerte:        String (mit der übergebenen Anzahl Nullen aufgefüllt)
// *
// ******************************************************************
function formatNum (initialValue_var, numToPad_int)
{
	var paddedValue_str = "";                         // String; enthält den mit Nullen aufgefüllten Wert
	var i = 0;                                     // Ganzzahl; für Schleifen verwendete Variable
	var initialValue_str = initialValue_var.toString();    // String; konvertiert den Parameter "initializeValue_var" explizit in einen String

	if (initialValue_str.length > numToPad_int)
	{
		// Fehler - Länge des Anfangswerts überschreitet bereits die aufzufüllende Zahl. Gibt den Wert initialValue_var ohne zusätzliche Nullen zurück
	} else {
		for (var i = 1; i <= (numToPad_int - initialValue_str.length); i++)
		{
			paddedValue_str = paddedValue_str + "0";
		}
	}
	paddedValue_str = paddedValue_str + initialValue_var;
	return paddedValue_str;
}

// Internet Explorer feststellen
var g_bIsInternetExplorer = navigator.appName.indexOf("Microsoft") != -1;

// FSCommand-Meldungen aus einem Flash-Film verarbeiten, wobei alle AICC-Flash-Vorlagenbefehle bei Bedarf SCORM zugewiesen werden.
function $TI_DoFSCommand(command, args){

	var $TIObj = g_bIsInternetExplorer ? $TI : document.$TI;

	// no-op, wenn kein SCORM API

	var myArgs = new String(args);
	var cmd = new String(command);
	var v = "";
	var err = "true";
	var arg1, arg2, n, s, i;
	var sep = myArgs.indexOf(",");
	if (sep > -1){
		arg1 = myArgs.substr(0, sep); // Name des Datenelements, das vom API abgerufen werden soll.
		arg2 = myArgs.substr(sep+1) 	// Name der Flash-Filmvariablen, die eingestellt werden soll.
	} else {
		arg1 = myArgs
	}
	if (!APIOK()) return;

	if (cmd.substring(0,3) == "LMS"){
		// "LMSxxx"-FSCommands verarbeiten (kompatibel mit fsSCORM-HTML-Vorlage)
		if ( cmd == "LMSInitialize" ){
			err = (APIOK() + "")
			// Das eigentliche LMSInitialize wird automatisch von der Vorlage aufgerufen.
		}	else if ( cmd == "LMSSetValue" ){
			alert('LMSSetValue: \r\rArg1: ' + arg1 + '\rArg2: ' + arg2);
			err = SCOSetValue(arg1,arg2)
		} else if ( cmd == "LMSFinish" ){
			err = SCOFinish()
			// Automatisch von der Vorlage verarbeitet, der Film kann es jedoch früher aufrufen.
		}	else if ( cmd == "LMSCommit" ){
			err = SCOCommit()
		}	else if ( cmd == "LMSFlush" ){
			// no-op
			// LMSFlush ist in SCORM nicht definiert, und sein Aufruf verursacht einen Testsuite-Fehler.
		}	else if ((arg2) && (arg2.length > 0)){
			if ( cmd == "LMSGetValue") {
				alert('LMSSetValue: \r\rArg1: ' + arg1 + '\rArg2: ' + arg2);
				$TIObj.SetVariable(arg2, SCOGetValue(arg1));
			}	else if ( cmd == "LMSGetLastError") {
				$TIObj.SetVariable(arg2, SCOGetLastError(arg1));
			}	else if ( cmd == "LMSGetErrorString") {
				$TIObj.SetVariable(arg2, SCOGetLastError(arg1));
			}	else if ( cmd == "LMSGetDiagnostic") {
				$TIObj.SetVariable(arg2, SCOGetDiagnostic(arg1));
			}	else {
				// für die unbekannte LMSGetxxxx-Erweiterung verfügbar ist
				v = eval('g_objAPI.' + cmd + '(\"' + arg1 + '\")');
				$TIObj.SetVariable(arg2,v);
			}
		} else if (cmd.substring(0,3) == "LMSGet") {
			err = "-2: No Flash variable specified"
		}
		// Ende der Verarbeitung "LMSxxx" cmds
	} else if ((cmd.substring(0,6) == "MM_cmi")||(cmd.substring(0,6) == "CMISet")) {
		// FSCommands der Macromedia-Lernkomponenten verarbeiten.
		// Diese verwenden Konventionen des AICC-HACP-Datenmodells, weisen also Daten aus AICC bei Bedarf in SCORM neu zu.
		var F_intData = myArgs.split(";");
		if (cmd == "MM_cmiSendInteractionInfo") {
			n = SCOGetValue("cmi.interactions._count");
			s = "cmi.interactions." + n + ".";
			// Grobe Fehler erfassen, damit der SCORM-Kompatibilitätstest nicht fehlschlägt.
			// Wenn für diese Interaktion keine ID angegeben wird, kann sie nicht aufgezeichnet werden.
			v = F_intData[2]
			if ((v == null) || (v == "")) err = 201; // Wenn keine ID vorhanden ist, kann nichts aufgezeichnet werden
			if (err =="true"){
				err = SCOSetValue(s + "id", v)
			}
			if (err =="true"){
				var re = new RegExp("[{}]","g")
				for (i=1; (i<9) && (err=="true"); i++){
					v = F_intData[i];
					if ((v == null) || (v == "")) continue
					if (i == 1){
						err = SCOSetValue(s + "timestamp", formatTimestamp(v))
					} else if (i == 3){
						err = SCOSetValue(s + "objectives.0.id", v)
					} else if (i == 4){
						err = SCOSetValue(s + "type", normalizeInteractionType(v))
					} else if (i == 5){
						// strip out "{" and "}" from response
						v = v.replace(re, "");
						err = SCOSetValue(s + "correct_responses.0.pattern", checkInteractionResponse(v))
					} else if (i == 6){
						// strip out "{" and "}" from response
						v = v.replace(re, "");
						err = SCOSetValue(s + "learner_response", checkInteractionResponse(v))
					} else if (i == 7){
						err = SCOSetValue(s + "result", normalizeInteractionResult(v))
					} else if (i == 8){
						err = SCOSetValue(s + "weighting", v)
					} else if (i == 9){
						err = SCOSetValue(s + "latency", v)
					}
				}
			}
		} else if (cmd == "MM_cmiSendObjectiveInfo"){
			err = SCOSetObjectiveData(F_intData[1], ".score.raw", F_intData[2])
			if (err=="true"){
				SCOSetObjectiveData(F_intData[1], ".status", normalizeStatus(F_intData[3]))
			}
		} else if ((cmd=="CMISetScore") ||(cmd=="MM_cmiSendScore")){
			err = SCOSetValue("cmi.score.raw", F_intData[0]);
		} else if ((cmd=="CMISetStatus") || (cmd=="MM_cmiSetLessonStatus")){
			var strTempStatus = normalizeStatus(F_intData[0]);
			if (strTempStatus == "passed" || strTempStatus == "failed")
			{
				err = SCOSetValue("cmi.success_status", normalizeStatus(F_intData[0]))
			} else {
				err = SCOSetValue("cmi.completion_status", normalizeStatus(F_intData[0]))
			}
		} else if (cmd=="CMISetTime"){
			err = SCOSetValue("cmi.session_time", formatTime(F_intData[0]))
		} else if (cmd=="CMISetCompleted"){
			err = SCOSetStatusCompleted()
		} else if (cmd=="CMISetStarted"){
			err = SCOSetValue("cmi.completion_status", "incomplete")
		} else if (cmd=="CMISetPassed"){
			SCOSetValue("cmi.completion_status", "completed");
			err = SCOSetValue("cmi.success_status", "passed")
		} else if (cmd=="CMISetFailed"){
			SCOSetValue("cmi.completion_status", "completed");
			err = SCOSetValue("cmi.success_status", "failed")
		} else if (cmd=="CMISetData"){
			err = SCOSetValue("cmi.suspend_data", F_intData[0])
		} else if (cmd=="CMISetLocation"){
			err = SCOSetValue("cmi.location", F_intData[0])
		} else if (cmd=="CMISetTimedOut"){
			err = SCOSetValue("cmi.exit", "time-out")
		} // Andere Lernkomponenten-FSCommands sind in diesem Kontext no-ops.
	} else {
		if (cmd=="CMIFinish" || cmd=="CMIExitAU"){
			err = SCOFinish()
		} else if (cmd=="CMIInitialize" || cmd=="MM_StartSession"){
			err = SCOInitialize()
		} else {
			// Unbekannter Befehl; kann eine API-Erweiterung aufrufen
			// Wenn Befehle über ein zweites Argument verfügen, wird angenommen, dass ein Wert erwartet wird, andernfalls wird angenommen, dass es sich einfach um einen Befehl handelt.
			if (eval('g_objAPI.' + cmd)) {
				v = eval('g_objAPI.' + cmd + '(\"' + arg1 + '\")');
				if ((arg2) && (arg2.length > 0)){
					$TIObj.SetVariable(arg2,v)
				} else {
					err = v
				}
			} else {
				err = "false"
			}
		}
	}
	// End of command translation and processing
	// handle detected errors, such LMS error returns
	if ((g_bShowApiErrors) && (err != "true")) {
		AlertUserOfAPIError(ExpandString(g_strFSAPIError, err, cmd, args))
	}
	return err
}
//-->
</script>
<body bgcolor="$BG" onunload="SCOFinish()" onbeforeunload="SCOFinish()">
<script type="text/javascript" language="JavaScript" name="earlyInit">
<!--
// Determine whether to attempt to initialize API before loading movie in case there is some ActionScript that fires off before the rest of the HTML page has finished loading.
// This is configurable by setting the global boolean (g_bInitializeOnLoad) in the beginning of this file.  Default value is TRUE.

// Look for SCORM API
g_varInterval = setInterval('waitForAPI()', (g_intPollSecs * 1000));

//-->
</script>
<!-- Im Film verwendete URLs-->
$MU
<!-- Im Film verwendeter Text-->
$MT
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=$FV,$JR,$NR,0" id="$TI" width="$WI" height="$HE" align="$HA">
<param name="allowScriptAccess" value="sameDomain" />
$PO
<embed $PEwidth="$WI" height="$HE" name="$TI" align="$HA" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer_de" />
</object>
</body>
</html>
