<?xml version="1.0" encoding="UTF-8"?>
<rmml>
<!--
$RCSfile:  rnmc_scorm_support.xml $
$Revision: 845 $

last change: $Date: 2008-11-19 16:46:47 +0300 (Ср, 19 ноя 2008) $
             $Author: toha $

	Lacerta Project
	version 1.0.0.1
	Copyright (C) 2008 RNMC
-->

<composition name="rnmc_SCORMLoader">
<script><![CDATA[
  // Тут хранятся пары: "название" - "значение"
  this.cmi_items = null;
  this.scorm_mode = "one";
  
  // Загрузка файл и составление пар
  function load()
  {
    var xmlNode = null;
    var xmlAttributeMap = null;
    
    var stepXML = scene.Utils.openXML(scene.scorm_xml);
    if (!stepXML)
      return false;
    else
      xmlNode = stepXML.XMLDocument.firstChild;

    if (xmlNode)
    {
      xmlNode = xmlNode.firstChild;
      while (xmlNode)
      {
        var defs = new Object();
        
        defs.name = xmlNode.nodeName;
        defs.value = xmlNode.textContent
        
        if (this.cmi_items == null)
          this.cmi_items = new Array();
          
        this.cmi_items.push(defs);
        
        xmlNode = xmlNode.nextSibling;
      }
    }
    
    var _sm = get_value("scorm_mode");
    
    if (_sm != "false")
      this.scorm_mode = _sm;
  }
  
  // Поиск по имени значения в массиве
  function get_value(name)
  {
    if (this.cmi_items == null)
      return "false";
      
    if (this.cmi_items.length <= 0)
      return "false";
      
    for (var i = 0; i < this.cmi_items.length; ++i)
    {
      if (this.cmi_items[i].name == name)
      {
        return this.cmi_items[i].value;
        break;
      }
    }
  }
]]></script>
</composition>

<composition name="rnmc_SCORMSupport">
<script><![CDATA[

	this.startTime = 0;

	this.attemptAbsoluteDurationLimit = 0;
	this.timeLimitAction = null;
  
  // Порог завершения,
  // two: если мера прогресса (progress_measure) больше или равна значению completionThreshold,
  //   то статус завершения устанавлиается (completion_status) в "completed",
  //   иначе в "incomplete",
  //   если мера прогресса не определена то в "not attempted"
	this.completionThreshold = 1;
	
  // two: если количество баллов набранное при работе с ЭУМ
  //   равно или более (>=) данного значения,
  //   то значение статуса успешности (success_status)
  //   устанавливается в "passed" иначе в "failed",
  //   если количество баллов не может быть подсчитано то в "unknown"
	this.scaledPassingScore = 1;

	this.SCORM = null;
  // статус завершения
	this.CMI_completion_status = "";
  // статус успешности
	this.CMI_success_status	= "";
  // мера прогресса
	this.CMI_progress_measure = "";	
  // статус выхода
	this.CMI_exit = "_nil_";	
	this.CMI_completion_threshold = "";
	this.CMI_scaled_passing_score = "";
	
// Время в секунда, по прошедствии которого,
// ЭУМ в котром нет подсчета результатов будет считаться полностью выполненым
	this.iTimeLimit = 5*60;
  
  // Предустановленные настройки SCORM
  // Если плеер не может выдасть эти настройки
  // то мы их будем брать из определенного xml-файла
	this.scorm_define = null;

	//	начальная инициализация
	function initializeScormSupport(){
		this.SCORM = API_1484_11;

		this.scorm_define = new Composition();
		this.scorm_define._class = "rnmc_SCORMLoader";
		this.scorm_define.parent = this;
		this.scorm_define.load();

		var newDate = new Date();
		this.startHours = newDate.getHours();
		this.startMinutes = newDate.getMinutes();
		this.startSeconds = newDate.getSeconds();

trace(this.startHours + ":" + this.startMinutes + ":" + this.startSeconds);

		this.SCORM.Initialize("");
//	cmi.completion_status
//	completed, incomplete, not attempted, unknown	
		this.CMI_completion_status = "not attempted";

	  this.CMI_success_status = "unknown";

//	причина выхода: "timeout", "suspend", "logout", "normal", ""
		this.CMI_exit = "_nil_";

		this.CMI_completion_threshold = this.SCORM.GetValue("cmi.completion_threshold");
		if (this.CMI_completion_threshold == "false" && this.scorm_define != null)
			this.CMI_completion_threshold = this.scorm_define.get_value("completionThreshold");
		if (this.CMI_completion_threshold != "false")
			this.completionThreshold = parseFloat(this.CMI_completion_threshold);
			
trace("this.completionThreshold == "+this.completionThreshold);

		this.CMI_scaled_passing_score = this.SCORM.GetValue("cmi.scaled_passing_score");
		if (this.CMI_scaled_passing_score == "false" && this.scorm_define != null)
			this.CMI_scaled_passing_score = this.scorm_define.get_value("scaledPassingScore");
		if (!isNaN(this.CMI_scaled_passing_score))
			this.scaledPassingScore = parseFloat(this.CMI_scaled_passing_score);
			
		this.SCORM.SetValue("cmi.exit", this.CMI_exit);
		this.SCORM.SetValue("cmi.success_status", this.CMI_success_status);
		this.SCORM.SetValue("cmi.completion_status", this.CMI_completion_status);

		this.SCORM.SetValue("cmi.session_time",
			this.convertIntegerToScormFormat(
				scene.Labwork.resultManager.getTotalDuration()));
	}

	function updateScormValues(){
		if (this.scorm_define != null && this.scorm_define.scorm_mode == "two")
			updateScormValuesTwo();
		else
			updateScormValuesOne();
	}

  function updateScormValuesOne(){
    if(scene.Labwork && scene.Labwork.resultManager){
      var newTotalResult = scene.Labwork.resultManager.getTotalResult();

trace("NEW TOTAL == " + newTotalResult);

      if (!isNaN(newTotalResult)) { // если есть подсчет результата
			// Считаем меру прогресса как отношение пройденых
			// шагов к общему числу шагов (учитываются только шаги где есть подсчет результата)
				var totalSteps = scene.Labwork.resultManager.getStepsTotal();
				var visitedResultSteps = 0;
				var allResultSteps = 0;			
				for(var i = 0; i  < totalSteps; i++){
					if (!scene.Labwork.resultManager.getStepResultCount(i))
						continue;
						
					++allResultSteps;
					if (scene.Labwork.resultManager.getStepVisited(i))
						++visitedResultSteps;
				}

				this.CMI_progress_measure = new Number(newTotalResult/100).toFixed(2).toString();
        this.SCORM.SetValue("cmi.progress_measure", this.CMI_progress_measure);

        if((visitedResultSteps/allResultSteps) >= this.completionThreshold)
          this.CMI_completion_status = "completed";
        else
					this.CMI_completion_status = "incomplete";
				this.SCORM.SetValue("cmi.completion_status", this.CMI_completion_status);

trace("this.scaledPassingScore == "+this.scaledPassingScore);
trace("newTotalResult == "+newTotalResult);
				if(newTotalResult >= this.scaledPassingScore*100)
					this.CMI_success_status = "passed";
				else
					this.CMI_success_status = "failed";
				this.SCORM.SetValue("cmi.success_status", this.CMI_success_status);
			} else { // если нет подсчета результатов
				var curTime = scene.Labwork.resultManager.getTotalDuration();

				if (curTime >= this.iTimeLimit)
					this.CMI_success_status = "passed";
				else
					this.CMI_success_status = "unknown";

        var totalSteps = scene.Labwork.resultManager.getStepsTotal();
        var visitedSteps = 0;
        for(var i = 0; i  < totalSteps; i++){
					if (scene.Labwork.resultManager.getStepVisited(i))
						++visitedSteps;
        }

				var fprogress_measure = new Number(visitedSteps/totalSteps).toFixed(2);
				if (fprogress_measure >= this.completionThreshold)
					this.CMI_completion_status = "completed";
				else
					this.CMI_completion_status = "incomplete";

				this.CMI_progress_measure = fprogress_measure.toString();

        this.SCORM.SetValue("cmi.progress_measure", this.CMI_progress_measure);
				this.SCORM.SetValue("cmi.completion_status", this.CMI_completion_status);
				this.SCORM.SetValue("cmi.success_status", this.CMI_success_status);				
			}

      this.SCORM.SetValue("cmi.session_time",
        this.convertIntegerToScormFormat(
          scene.Labwork.resultManager.getTotalDuration()));
    }
  }

  function updateScormValuesTwo()
  {
    if(scene.Labwork && scene.Labwork.resultManager)
    {
      // Количество всех шагов в модуле
      var steps_total = scene.Labwork.resultManager.getStepsTotal();
      // Количество всех шагов, где считается результат
      var all_rsteps_result = 0;
      // Количество шагов c подсчетом результата, в который "заглянул" ученик
      var all_rsteps_visited = 0;
      // Количество всех шагов, в который "заглянул" ученик
      var all_steps_visited = 0;	  
      
      for (var i = 0; i < steps_total; ++i)
      {
		if (scene.Labwork.resultManager.getStepVisited(i))
			++all_steps_visited;

        // Если в шаге считаются результаты
        if (scene.Labwork.resultManager.getStepResultCount(i))
        {
          ++all_rsteps_result;

          // Если посетили шаг
          if (scene.Labwork.resultManager.getStepVisited(i))
            ++all_rsteps_visited;
        }
      }
	  
	  var newProgressMeasure = "";
	  if (all_rsteps_result == 0)
	  { // Шагов с подсчетом результатов нет
		newProgressMeasure = all_steps_visited/steps_total;
	  }
	  else {
		if (all_rsteps_visited != 0)
		{ // Ученик зашодил в шаги с подсчетом результатов
			newProgressMeasure = all_rsteps_visited/all_rsteps_result;
		}
	  }

      if (!isNaN(newProgressMeasure))
	  {
		newProgressMeasure = new Number(newProgressMeasure).toFixed(2);
	    this.SCORM.SetValue("cmi.progress_measure", newProgressMeasure.toString());

		if(this.CMI_completion_status != "completed")
		{
        // Если "Мера прогресса" равна 0, то считаем, что
        // ученик вообще не прошел модуля
        // и устанавливаем cmi.completion_status = "not attempted"
		  if (newProgressMeasure <= 0)
		    this.CMI_completion_status = "not attempted";

        // Если "Мера прогресса" меньше "Порога завершения" 
        // то устанавливаем cmi.completion_status = "incomplete"
		  else if (newProgressMeasure < this.completionThreshold)
		    this.CMI_completion_status = "incomplete";

        // Если "Мера прогресса" больше, либо равна "Порогу завершения" 
        // то устанавливаем cmi.completion_status = "completed"
		  else if (newProgressMeasure >= this.completionThreshold)
		    this.CMI_completion_status = "completed";
		}

		var newTotalResult = scene.Labwork.resultManager.getTotalResult();
		if (!isNaN(newTotalResult)){
		  if (newTotalResult < 0)
				this.CMI_success_status = "unknown";
		  else if (newTotalResult >= this.scaledPassingScore * 100)
				this.CMI_success_status = "passed";
		  else
				this.CMI_success_status = "failed";
			} else {
				this.CMI_success_status = "unknown";
			}
    } else {
			this.CMI_completion_status = "not attempted";
			this.CMI_success_status    = "unknown";
	  }
	}
      this.SCORM.SetValue("cmi.session_time",
        this.convertIntegerToScormFormat(
          scene.Labwork.resultManager.getTotalDuration()));	  
	  this.SCORM.SetValue("cmi.completion_status", this.CMI_completion_status);
	  this.SCORM.SetValue("cmi.success_status",    this.CMI_success_status);
//	  this.SCORM.SetValue("cmi.exit",              this.CMI_exit);
  }
  
	function uninitializeScormSupport(){
		this.CMI_exit = "normal";
		this.SCORM.SetValue("cmi.exit", this.CMI_exit);
		updateScormValues();
		
		this.SCORM.Commit("");
		this.SCORM.Terminate("");
		this.SCORM = null;
	}

	function convertDateToScormFormat(obj){
		if(obj){
			var seconds = obj.getSeconds();
			var minutes = obj.getMinutes();
			var hours = obj.getHours();
			var resultString = "PT" + hours + "H" + minutes+ "M" + seconds + "S";
			return resultString;
		}
	}

	function convertIntegerToScormFormat(secondsValue){
		if(secondsValue){
			var seconds = secondsValue % 60;
			var minutes = parseInt(((secondsValue - seconds)/60) % 60);
			var hours = parseInt(((secondsValue - minutes*60) - seconds)/3600);		
			var resultString = "PT" + hours + "H" + minutes+ "M" + seconds + "S";
			return resultString;
		}
		return "PT0H0M0S";
	}
]]></script>
</composition>
</rmml>