<?xml version="1.0" encoding="UTF-8"?>
<rmml>
<!--
$RCSfile: rnmc_labwork_loader.xml,v $
$Revision: 941 $

last change: $Date: 2009-02-06 17:24:37 +0300 (Пт, 06 фев 2009) $
             $Author: toha $

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

<!--   ========================================================================================
    общие классы
  ======================================================================================== -->

<!--  ВКЛЮЧЕНИЕ ОБЩИХ КЛАССОВ -->
<include src="rnmc_stdObject.xml"/>
<include src="rnmc_stdMediaObject.xml"/>
<include src="rnmc_stdImage.xml"/>
<include src="rnmc_stdText.xml"/>
<include src="rnmc_stdInput.xml"/>
<include src="rnmc_stdInputEx.xml"/>
<include src="rnmc_stdAudio.xml"/>
<include src="rnmc_stdVideo.xml"/>
<include src="rnmc_stdFlash.xml"/>
<include src="rnmc_stdQt.xml"/>
<include src="rnmc_std3DObject.xml"/>
<include src="rnmc_stdAnimation.xml"/>
<include src="rnmc_stdShape.xml"/>
<include src="rnmc_stdSlider.xml"/>
<include src="rnmc_stdPLaycontrol.xml"/>
<include src="rnmc_stdMediaGroup.xml"/>
<include src="rnmc_stdControlGroup.xml"/>

<include src="rnmc_stdQuestion.xml"/>
<include src="rnmc_stdDragging.xml"/>
<include src="rnmc_stdIntegration.xml"/>
<include src="rnmc_stdUnion.xml"/>
<include src="rnmc_stdCollection.xml"/>
<include src="rnmc_stdButton.xml"/>
<include src="rnmc_stdCheckBox.xml"/>
<include src="rnmc_stdSlideshow.xml"/>
<include src="rnmc_stdTimer.xml"/>
<include src="rnmc_stdZone.xml"/>

<include src="rnmc_stdQtEmulation.xml"/>
<include src="rnmc_stdCrossword.xml"/>

<include src="rnmc_stdRectangle.xml"/>
<include src="rnmc_stdLine.xml"/>

<include src="rnmc_result_manager.xml"/>
<include src="rnmc_common_list.xml"/>
<include src="rnmc_result_panel.xml"/>
<include src="rnmc_steplist.xml"/>

<!-- Новый формат списка шагов -->
<include src="rnmc_stdSteplist.xml"/>
<include src="rnmc_local_indicator.xml"/>
<include src="rnmc_rollovermenu.xml"/>
<include src="rnmc_effect.xml"/>
<include src="rnmc_scrollmenu.xml"/>


<include src="rnmc_scorm_support.xml"/>
<!--   ========================================================================================
    шаблоны шагов лабораторной работы
  ======================================================================================== -->

<include src="rnmc_labwork_base.xml"/>
<include src="rnmc_labwork_information.xml"/>
<!-- 
  ШАБЛОНЫ DRAGGING и  CLASSIFICATION объединены в одном классе - rnmc_labwork_dragging
  Различаются по работе при задании type
-->
<include src="rnmc_labwork_dragging.xml"/>
<include src="rnmc_labwork_research.xml"/>
<include src="rnmc_labwork_question.xml"/>
<include src="rnmc_labwork_puzzle.xml"/>
<include src="rnmc_labwork_summary.xml"/>

<composition name="RNMC_Labwork_Loader" userEvents="evStepUnload">
<script><![CDATA[
// настройки лабораторной работы
// наличие списка шагов
  this.stepListVisible = false;

// наличие названия шага
  this.stepNameVisible = false;
  this.stepNameStyle = null;
  this.stepNameX = 0;
  this.stepNameY = 0;
  this.stepNameWidth = 0;
  this.stepNameHeight = 0;
  this.stepNameFormat = null;

  this.labTimerVisible = false;
  this.labTimerX = 0;
  this.labTimerY = 0;
  this.labTimerDepth = 0;
  this.labTimerStyle = null;
  this.labTimerPanelFormat = "%elapsed%";  
  this.labTimeFormat = "HH:MM:SS";

//  ОГРАНИЧЕНИЕ ВРЕМЕНИ ВЫПОЛНЕНИЯ
  this.disableButton = null; //  кнопка, которая будет дизаблить всю сцену
  this.labworkTimeLimitVisualisation = null;
  this.sceneEnabled = true;
  this.attemptAbsoluteDurationLimit = 0;
  this.completionThreshold = 0;
  this.onLabworkTimeOutActions = null;
  this.timeLimitAction = null;

//  ===========================================
//   объекты
//  список шагов
  this.stepList = null;
//   название шага
  this.stepName = null;

//
  this.resultPanelVisible = RESULT_PANEL_VISIBLE_FALSE;
  this.resultPanelActive = false;

  this.nextStepButton = null;

  // объект для управления и сбора статистики по заданиям
  this.resultManager = null;

// массивы с информацией по шагам
// названия шагов
  this.stepNames = null;
// файлы шагов
  this.stepSrcFiles = null;
// типы шаблонов шагов
  this.stepTypes = null;
// подсчет результатов
  this.stepResultCount = null;
// максимальное исло баллов для каждого шага
  this.stepMaxPoints = null;
// идентификаторы шагов
  this.stepIDs = null;

// объект текущего шага
  this.currentStep = null;
//  номер текущего шага
  this.currentStepIndex = -1;
  this.allowMultipleSounds = false;

  this.userGlobals = null;

//
	this.resultManager = new Composition();
	this.resultManager._class = "rnmc_ResultManager";
	this.resultManager.parent = this;
	this.resultManager.initResultManager();	
  
  // если вышло время выполнения всего модуля
  this.isTimeout = false;

  function loadLabwork(srcXMLFile){
    var xmlNode = null;
    var xmlAttributeMap = null;
    var xmlAttribute = null;

    var stepIndex = 1;

    this.childObjects = new Array();

    this.stepSrcFiles = new Array();
    this.stepTypes = new Array();
    this.stepNames = new Array();
    this.stepResultCount = new Array();
    this.stepMaxPoints = new Array();
    this.stepIDs = new Array();

    this.userGlobals = new Object();

    var labworkXML = scene.Utils.openXML(srcXMLFile);
    if (!labworkXML){
    // Если загружаемый файл не правильный - пишем в трэйсер и выходим
      trace("Файл " + srcXMLFile + " не является правильным XML файлом.");
      return false;
    } else {
      if (!labworkXML.XMLDocument || !labworkXML.XMLDocument.firstChild)
        return false;

      var tmp = new String(srcXMLFile).replace("/\/.g", "\\").split("\\")
      tmp.pop();
      var dirXMLFile = tmp.join("\\");

      xmlNode = labworkXML.XMLDocument.firstChild.firstChild;
      while(xmlNode){
        if(xmlNode.nodeName == "settings"){
        // считывание настроек всей лабораторной работы
          var settingNode = xmlNode.firstChild;
          while(settingNode){
            if(settingNode.nodeName == "results"){
            // настройки списка шагов
              xmlAttributeMap = settingNode.attributes;
              if(xmlAttributeMap){
                xmlAttribute = xmlAttributeMap.getNamedItem("selectRule");
                if (xmlAttribute != null && xmlAttribute.specified){
                  if((xmlAttribute.value).toUpperCase() == "LAST"){
                    this.resultManager.defaultResultSelectRule = SELECT_RESULT_LAST;
                  } else if((xmlAttribute.value).toUpperCase() == "BEST"){
                    this.resultManager.defaultResultSelectRule = SELECT_RESULT_BEST;
                  } else if((xmlAttribute.value).toUpperCase() == "AVERAGE"){
                    this.resultManager.defaultResultSelectRule = SELECT_RESULT_AVERAGE;
                  }
                };
              }
            } else if(settingNode.nodeName == "attemptAbsoluteDurationLimit"){
              if(settingNode.textContent){
                if(settingNode.textContent.indexOf(":") >= 0){
                //  значит время указано в строковом формате 
                  var timeParam = settingNode.textContent.split("");
                  this.attemptAbsoluteDurationLimit = 0;
                  if(timeParam.length == 2){
                  //  формат MM:SS
                    this.attemptAbsoluteDurationLimit = timeParam[0]*60 + timeParam[0];
                  } else if(timeParam.length == 3){
                  //  формат HH:MM:SS
                    this.attemptAbsoluteDurationLimit =
                      timeParam[0]*3600 + timeParam[1]*60 + timeParam[2];
                  }
                } else {
                //  указано просто количество секунд
                  this.attemptAbsoluteDurationLimit = parseInt(settingNode.textContent);
                }
                if(scene.ScormSupport && this.attemptAbsoluteDurationLimit > 0){
                  scene.ScormSupport.attemptAbsoluteDurationLimit = this.attemptAbsoluteDurationLimit;
                }
              //  инициализируем таймер
                if(resourceExists(def_timelimit_xml)){
                  var settingsXML = scene.Utils.openXML(def_timelimit_xml);
                  if (settingsXML){
                    var tempNode = settingsXML.XMLDocument.firstChild;
                    this.labworkTimeLimitVisualisation = new Composition();
                    this.labworkTimeLimitVisualisation._class = "rnmc_stdMediaGroup";
                    this.labworkTimeLimitVisualisation.visible = false;
                    this.labworkTimeLimitVisualisation.parent = this;
                    if(!this.labworkTimeLimitVisualisation.initFromNode(tempNode)){
                      this.labworkTimeLimitVisualisation.parent = null;
                      this.labworkTimeLimitVisualisation = null;
                    }
                  }
                }
              }
            } else if(settingNode.nodeName == "timeLimitAction"){
              if(settingNode.textContent){
                this.timeLimitAction = settingNode.textContent;
                if(scene.ScormSupport){
                  scene.ScormSupport.timeLimitAction = this.timeLimitAction;
                }
              }
            } else if(settingNode.nodeName == "completionThreshold"){
              if(settingNode.textContent){
                this.completionThreshold = parseFloat(settingNode.textContent);
                if(scene.ScormSupport && this.completionThreshold > 0){
                  scene.ScormSupport.completionThreshold = this.completionThreshold;
                }
              }
            } else if(settingNode.nodeName == "steplist"){
            // настройки списка шагов
              xmlAttributeMap = settingNode.attributes;
              if(xmlAttributeMap){
                xmlAttribute = xmlAttributeMap.getNamedItem("visible");
                if(xmlAttribute != null
                && xmlAttribute.specified
                && xmlAttribute.value == "true"){
                  this.stepListVisible = true;
                }
              }
            } else if(settingNode.nodeName == "resultpanel"){
              xmlAttributeMap = settingNode.attributes;
              if(xmlAttributeMap){
                xmlAttribute = xmlAttributeMap.getNamedItem("visible");
                if(xmlAttribute != null && xmlAttribute.specified){
                  if (xmlAttribute.value == "true"){
                    this.resultPanelVisible = RESULT_PANEL_VISIBLE_TRUE;
                  } else if(xmlAttribute.value == "true"){
                    this.resultPanelVisible = RESULT_PANEL_VISIBLE_FALSE;
                  }
                }
              }
            } else if(settingNode.nodeName == "stepname"){
              xmlAttributeMap = settingNode.attributes;
              if(xmlAttributeMap){
                xmlAttribute = xmlAttributeMap.getNamedItem("visible");
                if(xmlAttribute != null
                && xmlAttribute.specified
                && xmlAttribute.value == "true"){
                  this.stepNameVisible = true;
                }
                xmlAttribute = xmlAttributeMap.getNamedItem("style");
                if(xmlAttribute != null && xmlAttribute.specified){
                  this.stepNameStyle = xmlAttribute.value;
                }
                xmlAttribute = xmlAttributeMap.getNamedItem("x");
                if(xmlAttribute != null && xmlAttribute.specified){
                  this.stepNameX = parseInt(xmlAttribute.value);
                }
                xmlAttribute = xmlAttributeMap.getNamedItem("y");
                if(xmlAttribute != null && xmlAttribute.specified){
                  this.stepNameY = parseInt(xmlAttribute.value);
                }
                xmlAttribute = xmlAttributeMap.getNamedItem("width");
                if(xmlAttribute != null && xmlAttribute.specified){
                  this.stepNameWidth = parseInt(xmlAttribute.value);
                }
                xmlAttribute = xmlAttributeMap.getNamedItem("height");
                if(xmlAttribute != null && xmlAttribute.specified){
                  this.stepNameHeight = parseInt(xmlAttribute.value);
                }
                xmlAttribute = xmlAttributeMap.getNamedItem("format");
                if(xmlAttribute != null && xmlAttribute.specified){
                  this.stepNameFormat = xmlAttribute.value;
                }
              }
            } else if((settingNode.nodeName).toLowerCase() == "localindicator"){
              xmlAttributeMap = settingNode.attributes;
              if(xmlAttributeMap){
                xmlAttribute = xmlAttributeMap.getNamedItem("visible");
                if(xmlAttribute != null && xmlAttribute.specified){
                  if ((xmlAttribute.value).toLowerCase() == "true"){
                    this.localStepIndicatorVisible = STEP_INDICATOR_VISIBLE_TRUE;
                  } else if((xmlAttribute.value).toLowerCase() == "false"){
                    this.localStepIndicatorVisible = STEP_INDICATOR_VISIBLE_FALSE;
                  }
                } 
              }
            }
            settingNode = settingNode.nextSibling;
          }
        } else if(xmlNode.nodeName == "steps"){
          var stepNode = xmlNode.firstChild;
          while(stepNode){
            if(stepNode.nodeName == "step"){
              xmlAttributeMap = stepNode.attributes;
              if(xmlAttributeMap){
                var stepType = null;
                var stepName = null;
                var stepXmlFile = null;
                var stepCountResult = false;
                var stepResultSelectRule = null;
                var stepMaxPoints = 0;
                var stepID = null;
                xmlAttribute = xmlAttributeMap.getNamedItem("type");
                if(xmlAttribute != null && xmlAttribute.specified){
                  stepType = xmlAttribute.value;
                }
                xmlAttribute = xmlAttributeMap.getNamedItem("resultCount");
                if(xmlAttribute != null && xmlAttribute.specified){
                  if((xmlAttribute.value).toLowerCase() == "true"){
                    stepCountResult = true;
                  } else if((xmlAttribute.value).toLowerCase() == "false"){
                    stepCountResult = false;
                  }
                }
                xmlAttribute = xmlAttributeMap.getNamedItem("selectRule");
                if (xmlAttribute != null && xmlAttribute.specified){
                  if((xmlAttribute.value).toUpperCase() == "LAST"){
                    stepResultSelectRule = SELECT_RESULT_LAST;
                  } else if((xmlAttribute.value).toUpperCase() == "BEST"){
                    stepResultSelectRule = SELECT_RESULT_BEST;
                  } else if((xmlAttribute.value).toUpperCase() == "AVERAGE"){
                    stepResultSelectRule = SELECT_RESULT_AVERAGE;
                  }
                };
                xmlAttribute = xmlAttributeMap.getNamedItem("maxPoints");
                if(xmlAttribute != null && xmlAttribute.specified){
                  stepMaxPoints = parseInt(xmlAttribute.value);
                }
                xmlAttribute = xmlAttributeMap.getNamedItem("src");
                if(xmlAttribute != null && xmlAttribute.specified){
                  stepXmlFile = scene.Utils.makePath(dirXMLFile, xmlAttribute.value);
                  
                  var stepXML = scene.Utils.openXML(stepXmlFile);
                  if (!stepXML){
                    trace("ОШИБКА: Не существующий шаг.");
                  } else {
                    stepXML.XMLDocument.source = stepXML.src;
                    var tempNode = stepXML.XMLDocument.firstChild.firstChild;
                    while(tempNode){
                      if(tempNode.nodeName == "settings"){
                        var setNode = tempNode.firstChild;
                        while(setNode){
                          if(setNode.nodeName == "name"
                            && setNode.textContent != ""){
                            stepName = setNode.textContent;
                          }
                          setNode = setNode.nextSibling;
                        }
                      }
                      tempNode = tempNode.nextSibling;
                    }
                  }
                }
                xmlAttribute = xmlAttributeMap.getNamedItem("id");
                if(xmlAttribute != null && xmlAttribute.specified)
                  stepID = xmlAttribute.value;
                if(!stepName)
                  stepName = "Шаг " + stepIndex;
                if(stepType && stepXmlFile){
                  this.stepNames.push(stepName);
                  this.stepTypes.push(stepType);
                  this.stepSrcFiles.push(stepXmlFile);
                  this.resultManager.addStep(stepName, stepType,
                    stepCountResult, stepResultSelectRule);
                  this.stepIDs.push(stepID);
                  stepIndex++;
                }
              }
            }
            stepNode = stepNode.nextSibling;
          }
          stepNode = null;
        } 
        xmlNode = xmlNode.nextSibling;
      }
      this.loadChildObjects(labworkXML.XMLDocument.firstChild);
    }
    //this.resultManager.initResultManager(this.stepSrcFiles.length);
    if(this.stepListVisible){
      if(USE_OLD_STEPLIST_FORMAT){
        //  СТАРАЯ ВЕРСИЯ СПИСКА ШАГОВ
        this.stepList = new Composition();
        this.stepList._class = "rnmc_StepList";
        this.stepList.parent = this;
        this.stepList.visible = false;
        this.stepList.depth = -5000;
        if(!this.stepList.loadStepList(this.stepNames)){
          this.stepList.parent = null;
          this.stepList = null;
        } else {
          this.stepList.visible = true;
        }
      } else {
      //  ПОСЛЕДНЯЯ ВЕРСИЯ СПИСКА ШАГОВ
        var stepListSettingsFile = scene.step_list_xml;
        if(!resourceExists(stepListSettingsFile)){
          trace("ОШИБКА: Файл настроек списка шагов " + stepListSettingsFile + " не найден.");
          return false;
        }
        var settingsXML = scene.Utils.openXML(stepListSettingsFile);
        if (!settingsXML){
      // Если загружаемый файл не правильный - пишем в трэйсер и выходим
        } else {
          xmlNode = settingsXML.XMLDocument.firstChild;
          this.stepList = new Composition();
          this.stepList._class = "rnmc_stdStepList";
          this.stepList.parent = this;
          this.stepList.visible = false;
          if(!this.stepList.initFromNode(xmlNode)){
            this.stepList.parent = null;
            this.stepList = null;
          } else {
            this.stepList.showObject();  
          }
        }
      }
    }
  //  если определена панель результатов
    if(this.resultPanelVisible == RESULT_PANEL_VISIBLE_TRUE){
      this.resultPanelActive = true;
      this.resultPanel = new Composition();
      this.resultPanel._class = "rnmc_ResultPanel";
      this.resultPanel.parent = this;
      this.resultPanel.visible = false;
      this.resultPanel.depth = -4000;
      this.resultPanel.initFromFile(scene.result_panel_xml);
      this.resultPanel.showObject();
    }
  //  если определен визуализатор ошибок
    if(this.localStepIndicatorVisible == STEP_INDICATOR_VISIBLE_TRUE){
      this.localStepIndicator = new Composition();
      this.localStepIndicator._class = "rnmc_LocalSTepIndicator";
      this.localStepIndicator.visible = false;
      this.localStepIndicator.parent = this;
      var initResult = this.localStepIndicator.initFromFile(scene.step_indicator_xml);
      if(!initResult){
trace("#FF0000Ошибка: локальный индикатор ошибок/подсказок не может быть инициализирован из-за ошибок в файле настроек " + scene.step_indicator_xml);
        this.localStepIndicator.parent = null;
        this.localStepIndicator = null;
      }
    }
    this.stepName = new Text();
    this.stepName.visible = false;
    this.stepName.x = this.stepNameX;
    this.stepName.y = this.stepNameY;
    this.stepName.width = this.stepNameWidth;
    this.stepName.height = this.stepNameHeight;
    if(this.stepNameStyle && scene.StyleManager.styleExists(this.stepNameStyle))
      this.stepName.style = this.stepNameStyle;
    this.stepName.format = stepNameFormat;
    this.stepName.parent = this;

    if (this.childObjects){
      for(var i = 0; i < this.childObjects.length; i++){
        if(this.childObjects[i].visibility == OBJECT_VISIBILITY_TRUE){
          this.childObjects[i].showObject();
        }
      }
    }

    if(this.attemptAbsoluteDurationLimit > 0){
      this.labTimer = new Composition();
      this.labTimer._class = "rnmc_stdTimer";
      this.labTimer.visible = false;
      this.labTimer.parent = this;
      this.labTimer.timeOut = this.attemptAbsoluteDurationLimit*1000;
      this.labTimer.timerVisible = false;
      this.labTimer.setTimeoutCallback(this, this.onLabworkTimeOut);
      this.labTimer.playObject();
    }
    if(this.labworkTimeLimitVisualisation){
      this.labworkTimeLimitVisualisation.showObject();
    }

    return true;
  }

  function unloadModule() {
  //  сообщаем менеджеру статистики об окончании шага
  //  массив с результатми всех объектов в шаге
  //  в том числе objectives
    var resultsArray  = new Array();
    this.currentStep.getStepResult(resultsArray);
    this.resultManager.onFinishStep(
      resultsArray,
      this.currentStep.getStepErrors(),
      this.currentStep.getStepHelps());
  //  обновляем SCORM значения 
    if(scene.ScormSupport)
      scene.ScormSupport.uninitializeScormSupport();
  }
  

//  загрузка медиа компонентов, глобальных для всего модуля
  function loadChildObjects(srcNode){
    //  тяжёлые объекты, такие как коллекция и слайдшоу не грузяццца!!!
    var xmlNode = srcNode.firstChild;
    while(xmlNode){
      if(xmlNode.nodeName == "actions"){
        this.onLabworkTimeOutActions = scene.Utils.parseActionsNode(xmlNode, "onTimeLimit");
        trace("onLabworkTimeOutActions == " + this.onLabworkTimeOutActions);
      } else {
        var newObject = scene.Utils.initStdObjectFromNode(xmlNode, this);
        if(newObject)
          this.childObjects.push(newObject);
      }
      xmlNode = xmlNode.nextSibling;
    }
    return true;
  }

  function startStepID(id){
    for (var i = 0; i < this.stepIDs.length; ++i){
      if (id == this.stepIDs[i]) {
        startStep(i);
        break;
      }
    }
  }
  

// загрузка шага лабораторной работы по номеру шага
    function startStep(index){
//trace("startStep(" + index + ")");
    var xmlNode = null;
    var xmlAttributeMap = null;
    var xmlAttribute = null;

    if(index < 0 || index >= this.stepNames.length){
      trace("Ошибка: неверный номер шага.");
      return;
    } else {
      // объект создаваемого шага
      var newStep = null;
      // узел, из которого будет инициализироваться новый шаг
      var newStepNode = null;

      switch(this.stepTypes[index]){
      case "information":     // информационный шаблон
        newStep = new Composition;
        newStep._class = "rnmc_labwork_information";
        newStep.parent = this;
        newStep.depth = 10;
        newStep.visible = false;
        break;
      case "dragging":      // перетаскивание
        newStep = new Composition();
        newStep._class = "rnmc_labwork_dragging";
        newStep.parent = this;
        newStep.depth = 10;
        newStep.visible = false;
        newStep.type = "RNMC_LABWORK_DRAGGING";
        break;
      case "classification":      // классификация объектов
        newStep = new Composition();
        newStep._class = "rnmc_labwork_dragging";
        newStep.parent = this;
        newStep.depth = 10;
        newStep.visible = false;
        newStep.type = "RNMC_LABWORK_CLASSIFICATION";
        break;
      case "question":      // ответы на вопросы
        newStep = new Composition();
        newStep._class = "rnmc_labwork_question";
        newStep.parent = this;
        newStep.depth = 10;
        newStep.visible = false;
        break;
      case "research":      // исследование зон
        newStep = new Composition();
        newStep._class = "rnmc_labwork_research";
        newStep.parent = this;
        newStep.depth = 10;
        newStep.visible = false;
        break;
      case "embedflash":      // флэш с подсчётом результатов
        newStep = new Composition();
        newStep._class = "rnmc_labwork_embedflash";
        newStep.parent = this;
        newStep.depth = 10;
        newStep.visible = false;
        break;
      case "puzzle":      // мозайка (МХК)
        newStep = new Composition();
        newStep._class = "rnmc_labwork_puzzle";
        newStep.parent = this;
        newStep.depth = 10;
        newStep.visible = false;
        break;
      case "summary":      // результаты работы
        newStep = new Composition();
        newStep._class = "rnmc_labwork_summary";
        newStep.parent = this;
        newStep.depth = 10;
        newStep.visible = false;
        break;
      default:
        newStep = this.startStepEx(this.stepTypes[index]);
        break;
      }

      var stepXML = scene.Utils.openXML(this.stepSrcFiles[index]);
      if (!stepXML)
        return false;
      else
        xmlNode = stepXML.XMLDocument.firstChild;
      if(newStep){
        newStep.id = "step"+index;

        newStep.labTimerVisible = this.labTimerVisible;
        newStep.labTimerX = this.labTimerX;
        newStep.labTimerY = this.labTimerY;
        newStep.labTimerDepth = this.labTimerDepth;
        newStep.labTimerStyle = this.labTimerStyle;
        newStep.labTimerPanelFormat = this.labTimerPanelFormat;
        newStep.labTimeFormat = this.labTimeFormat;

//        if(!newStep.loadStep(xmlNode)){
//          trace("ОШИБКА: загрузить шаг " + index + " не удалось.");
//          newStep.parent = null;
//          newStep = null;
//        } else {
        {
          if(this.currentStep){
          //  сообщаем менеджеру статистики об окончании шага
          //  массив с результатми всех объектов в шаге
          //  в том числе objectives
            var resultsArray  = new Array();
            this.currentStep.getStepResult(resultsArray);
            this.resultManager.onFinishStep(
              resultsArray,
              this.currentStep.getStepErrors(),
              this.currentStep.getStepHelps());
          //  обновляем SCORM значения 
            if(scene.ScormSupport){
              scene.ScormSupport.updateScormValues();
            }  
            scene.SoundManager.onFinishStep();
            fireEvent("evStepUnload");
            this.currentStep.exitStep();
            this.currentStep.visible = false;
            this.currentStep.parent = null;
            this.currentStep = null;
            if(this.timerObject){
              this.timerObject.parent = null;
              this.timerObject = null;
            }
          }

          newStep.loadStep(xmlNode);
          this.currentStep = newStep;
          newStep = null;
          var multipleSounds = this.allowMultipleSounds;
          if(this.currentStep.allowMultipleSounds != 'undefined'
          && this.currentStep.allowMultipleSounds != null)
            multipleSounds = this.currentStep.allowMultipleSounds;

        //  если для всей лабораторной работы опрделена панель результатов
        //  то в зависимости от настроек конкретного шага - показывыаем её или нет
          if(this.resultPanelVisible == RESULT_PANEL_VISIBLE_TRUE){ 
            if(this.currentStep.resultPanelVisible == RESULT_PANEL_VISIBLE_FALSE){
              this.resultPanel.visible = false;
              this.resultPanelActive = false;
            } else if(this.currentStep.resultPanelVisible
              == RESULT_PANEL_VISIBLE_TRUE ||
              this.currentStep.resultPanelVisible
              == RESULT_PANEL_VISIBLE_UNDEFINED){
              this.resultPanel.visible = true;
              this.resultPanelActive = true;
            }
          }
        //  индикатор текущих ошибок, подсказок в шаге
          if(this.localStepIndicatorVisible
          == STEP_INDICATOR_VISIBLE_TRUE
            && this.localStepIndicator){
            if(this.currentStep.localStepIndicatorVisible
            == STEP_INDICATOR_VISIBLE_FALSE){
              this.localStepIndicator.hideObject();
            } else if(this.currentStep.localStepIndicatorVisible
            == STEP_INDICATOR_VISIBLE_TRUE ||
            this.currentStep.localStepIndicatorVisible
            == STEP_INDICATOR_VISIBLE_UNDEFINED){
              this.localStepIndicator.showObject();
            }
          }

          scene.SoundManager.onStartStep(multipleSounds);
          this.currentStep.visible = true;
          //  сохраняем номер текущего шага (для функций перехода на шаг назад/вперёд)
          this.currentStepIndex = index;
          // сообщаем менеджеру статистики о начале шага
          this.resultManager.onStartStep(index);
          if(this.stepList){
            this.stepList.selectCurrentStep(index);
          }

        //
          this.stepName.visible = false;

          this.stepName.Visible = this.stepNameVisible;
          if(scene.StyleManager.styleExists(this.stepNameStyle))
            this.stepName.style = this.stepNameStyle;
          this.stepName.x = this.stepNameX ;
          this.stepName.y = this.stepNameY;
          this.stepName.width = this.stepNameWidth;
          this.stepName.height = this.stepNameHeight;
          this.stepName.format = this.stepNameFormat;

          this.currentStep.startStep();

        //  отображение названия шага
          if (this.stepName.format != 'undefined'
            && this.stepName.format != null){
            var formatString = this.stepName.format;

            var re = new RegExp("(%total%)", "g");
            formatString = formatString.replace(re, this.stepNames.length);

          // старый (смысл неверен)
            re = new RegExp("(%elapsed%)", "g");
            formatString = formatString.replace(re, index + 1);
          //  новый
            re = new RegExp("(%index%)", "g");
            formatString = formatString.replace(re, index + 1);

            re = new RegExp("(%remaining%)", "g");
            formatString = formatString.replace(re, this.stepNames.length - index);

            re = new RegExp("(%name%)", "g");
            formatString = formatString.replace(re, this.stepNames[index]);

            this.stepName.value = formatString;
          }
          else
            this.stepName.value = this.stepNames[index];
          this.stepName.visible = this.stepName.Visible;
        }
      }
    }
  }

// Эту функцию необходимо переопределить,
// что бы вводить новые специфичные типы шагов (не шаблонные шаги)
  function startStepEx(stepType){
    trace("ОШИБКА: Неизвестный тип шага (type)");
    return null;
  }

// стартует предыдущий шаг
  function startPreviousStep(){
//trace("Переход к предыдущему шагу");
    if(this.currentStepIndex > 0){
      this.startStep(this.currentStepIndex - 1);
    } else {
      trace("Перейти на шаг назад нельзя.");
    }
  }

// стартует следующий шаг
  function startNextStep(){
    //trace("Переход к следующему шагу");
    if(this.currentStepIndex < (this.stepSrcFiles.length - 1)){
      this.startStep(this.currentStepIndex + 1);
    } else {
      trace("Перейти на шаг вперёд нельзя.");
    }
  }

// стартует первый шаг
  function startFirstStep(){
    this.startStep(0);
  }

// стартует последний шаг
  function startLastStep(){
    this.startStep(this.stepSrcFiles.length - 1);
  }

// стартует шаг summary
  function startSummaryStep(){
    for(var i = this.currentStepIndex; i < this.stepTypes.length; i++){
      if(this.stepTypes[i] == "summary"){
        this.startStep(i);
        return;
      }
    }
  }

  function buttonDispatcher(btnId){
    switch(btnId){
    case "nextstep":
      this.startNextStep();
      break;
    }
  }

  function notifyStepComplete(stepResult){
//trace("Loader: onStepComplete()");
    //this.resultManager.onFinishStep();
  }

// функция установки других параметров элемента "Название шага"
// дожна вызываться в startStep() шага !!!!!!!!!!!!!
  function setStepNameParams(newTextStyle, newTextX, newTextY,
    newTextWidth, newTextHeight, newTextFormat, newTextVisible){
    if(newTextStyle != undefined){
      if(scene.StyleManager.styleExists(newTextStyle))
        this.stepName.style = newTextStyle;
    }
    if (newTextVisible != undefined)
      this.stepName.Visible = newTextVisible;
    if(newTextX != undefined)
      this.stepName.x = newTextX;
    if(newTextY != undefined)
      this.stepName.y = newTextY;
    if(newTextWidth != undefined)
      this.stepName.width = newTextWidth;
    if(newTextHeight != undefined)
      this.stepName.height = newTextHeight;
    if(newTextFormat != undefined)
      this.stepName.format = newTextFormat;
  }

  function onStepTimeout(){
trace("#FF0000Время на выполнение шага кончилось!!!");
  }
  
  function onLabworkTimeOut(){
    trace("ACHTUNG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1");
    if(this.onLabworkTimeOutActions){
      for(var i = 0; i < this.onLabworkTimeOutActions.length; i++){
        this.dispatchAction(this.onLabworkTimeOutActions[i]);
      }
    }
  }

//  удаляет глобальную переменную с некоторым значением
  function removeGlobalProperty(propertyName, propertyValue){
    if(this.userGlobals[propertyName] != undefined){
      this.setGlobalProperty[propertyName] = null;
      delete this.setGlobalProperty[propertyName];
    }
  }

//  изменняет значение глобальной переменной
  function setGlobalProperty(propertyName, propertyValue){
    if(this.userGlobals[propertyName] != undefined){
      this.userGlobals[propertyName]= propertyValue;
    } else {
      this.userGlobals[propertyName]= propertyValue;
    }
  }

//  возращает значение глобальной переменной
  function getGlobalProperty(propertyName){
    if(this.userGlobals[propertyName] != undefined){
      return this.userGlobals[propertyName];
    } else {
      return null;
    }
  }

//  тестирует значение переменной на равентсво некоторому значению
  function testGlobalProperty(propertyName,  propertyValue){
    if(this.getGlobalProperty(propertyName) == propertyValue){
      return true;
    } else {
      return false;
    }
  }

  function testGlobalCondition(conditionId){
  }

//
  function addNewResult(newResult){
    if(this.resultPanel && this.resultPanelActive){
      this.resultPanel.addResult(newResult, "");
    }
  }

  function dispatchAction(singleAction){
    for (var i = 0; i < singleAction.length; ++i)
      singleAction[i] = scene.Utils.trim(singleAction[i]);

    this.doAction(singleAction);
  }

//  пришлось сюда вствить всю обработку 
  function doAction(singleAction){
    switch(singleAction[0]){
    case "disableScene":
      this.disableScene();
      break;
    case "displayExitMessage":
    
      break;
    case "testCondition":
      if(this.globalConditions){
        for(var i = 0; i < this.globalConditions.length; i++){
          if(this.globalConditions[i].id == singleAction[1]){
            this.testCondition(this.globalConditions[i]);
          }
        }
      }
      break;
    case "showObject":
      for(var i = 0; i < this.childObjects.length; ++i){
        if(this.childObjects[i].id == singleAction[1]){
          if(!this.childObjects[i].disabled){
            this.childObjects[i].showObject();
          }
        }
      }
      break;
    case "showObjectOnly":
      for(var i = 0; i < this.childObjects.length; ++i){
        if(this.childObjects[i].id == singleAction[1]){
          this.childObjects[i].showObject();
        } else {
          this.childObjects[i].hideObject();
        }
      }
      break;
    case "hideObject":
      for(var i = 0; i < this.childObjects.length; i++){
        if(this.childObjects[i].id == singleAction[1]){
          this.childObjects[i].hideObject();
        }
      }
      break;
    case "hideAllObjects":
      for(var i = 0; i < this.childObjects.length; i++){
        this.childObjects[i].hideObject();
      }
      break;
    case "resetObject":
      for(var i = 0; i < this.childObjects.length; ++i){
        if(this.childObjects[i].id == singleAction[1]){
          if(!this.childObjects[i].disabled)
            this.childObjects[i].resetObject();
        }
      }
      break;
    case "checkObject":
      for(var i = 0; i < this.childObjects.length; ++i){
        if(this.childObjects[i].id == singleAction[1]){
          if(!this.childObjects[i].disabled)
            this.childObjects[i].checkObject();
        }
      }
      break;      
    case "setPosition":
      var newPosX = 0;
      var newPosY = 0;
      var newPosWidth = 0;
      var newPosHeight = 0;
      var newPosDepth = 0;
      var newPosRatio = null;
      var newPositionParam = (singleAction[1]).split(",");
      if(newPositionParam.length < 6){
        trace("#FF0000Ошибка - неверный формат параметров в действии setPosition:" + singleAction[1]);
        return;
      }
      var objectId = newPositionParam[0];
      for(var i = 0; i < this.childObjects.length; i++){
        if(this.childObjects[i].id == objectId){
          if(newPositionParam[1])
            newPosX = newPositionParam[1];
          if(newPositionParam[2])
            newPosY = newPositionParam[2];
          if(newPositionParam[3])
            newPosWidth = newPositionParam[3];
          if(newPositionParam[4])
            newPosHeight = newPositionParam[4];
          if(newPositionParam[5])
            newPosDepth = newPositionParam[5];
          if(newPositionParam[6])
            newPosRatio = newPositionParam[6];
          this.childObjects[i].setPosition(newPosX, newPosY, newPosWidth, newPosHeight, newPosDepth, newPosRatio);
        }
      }
      break;
    case "resetPosition":
      for(var i = 0; i < this.childObjects.length; i++){
        if(this.childObjects[i].id == singleAction[1]){
          this.childObjects[i].resetPosition();
        }
      }
      break;
    case "fireLink":
      scene.Utils.fireLink(singleAction[1]);
      break;
    case "goToStep":
      this.startStep(parseInt(singleAction[1]));
      break;
    case "goToStepWithId":
      this.startStepID(singleAction[1]);
      break;
    case "goPreviousStep":
      this.startPreviousStep();
      break;
    case "goNextStep":
      this.startNextStep();
      break;
    case "goFirstStep":
      this.startFirstStep();
      break;
    case "goLastStep":
      this.startLastStep();
      break;
    case "goToSummary":
      this.startSummaryStep();
      break;
    case "timeOutObject": 
      this.isTimeout = true;
      
      if (this.currentStep && "onTimeout" in this.currentStep){
        this.currentStep.onTimeout(singleAction[1]);
      }
      break;
    }
  }

  function setStateParamsForObject(objectId, newStateParams){
    if(!this.savedStatesArray){
      this.savedStatesArray = new Array();
    }
    var bFound = false;
    for(var i = 0; i < this.savedStatesArray.length; i++){
      if(this.savedStatesArray[i].id == objectId){
        this.savedStatesArray[i] = newStateParams;
        bFound = true;
      }
    }
    if(!bFound){
      newStateParams.id = objectId;
      this.savedStatesArray.push(newStateParams);
    }
  }

  function getStateParamsForObject(objectId){
    if(this.savedStatesArray){
      for(var i = 0; i < this.savedStatesArray.length; i++){
        if(this.savedStatesArray[i].id == objectId){
          return this.savedStatesArray[i];
        }
      }
    }
    return null;
  }

  function onStatisticsChanged(eventId, eventParam){
    /*
    switch(eventId){
    case ON_STEP_RESULT_CHANGED:
      break;
    case ON_STEP_ERRORS_CHANGED:
      break;
    case ON_STEP_HELPS_CHANGED:
      break;
    }
    */
  }

  function disableScene(){
    if(this.stepList){
      this.stepList.enabled = false;
    }
  }

  function getObjectProperty(objName, objProperty){
    for(var i = 0; i < this.childObjects.length; i++){
      if(this.childObjects[i].id == objName)
        return this.childObjects[i].getObjectProperty(".", objProperty);
    }

    return null;
  }

  function setObjectProperty(objName, objProperty, propertyValue){
    for(var i = 0; i < this.childObjects.length; i++){
      if(this.childObjects[i].id == objName)
        this.childObjects[i].setObjectProperty(".", objProperty, propertyValue);
    }
  }

  function getChildObject(objID){
    for(var i = 0; i < this.childObjects.length; i++){
      if(this.childObjects[i].id == objID)
        return this.childObjects[i];
    }

    return null;
  }  
]]></script>
</composition>
</rmml>
