<?xml version="1.0" encoding="UTF-8"?>
<!--
$RCSfile: rnmc_stdUnion.xml $
$Revision: 938 $

last change: $Date: 2009-02-06 13:34:59 +0300 (Пт, 06 фев 2009) $
             $Author: toha $

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

<rmml>
<composition name="rnmc_stdUnion" class="rnmc_stdMediaGroup">
<script><![CDATA[
  this.type = "rnmc_Union";

//  =================================================================
//  настройки элемента

//  вывод вопросов в произвольном порядке
  this.questionsRandom = true;
//  количество вопросов которое необходимо задать (-1 - все)
  this.questionsToDisplay = -1;
//  возможность перебора вопросов
  this.allowSelection = true;
//  разрешено повторно отвечать на вопросы
  this.allowMultipleAttempts = true;
// запрещено показывать правильные оптношения
  this.showCorrectRelationsAttempts = false;
//  стиль запрета на повторное отвечание на один и тот же вопрос
  this.excludeStyle = QUESTION_DISABLE;
//  зацикливание набора вопросов (т.е. после последнего переходит к первому и наоборот)
  this.selectionCycling = true;

//  произвольный порядок вывода ответов на экран
//  настройка учитываецца если не указано иного в отдельном вопросе
  this.answersRandom = true;

//  автопереход к слежующему вопросу
  this.autoSkip = false;

//  направления перехода при autoskip (когда отвечают на вопрос -
//  происходит автопереход к другому возможному вопросу)
//  this.autoSkipDirection = QUESTION_AUTOSKIP_BACK; // - к предыдущему возможному в наборе
//  this.autoSkipDirection = QUESTION_AUTOSKIP_RANDOM; // - к произвольному возможному в наборе
  this.autoSkipDirection = QUESTION_AUTOSKIP_FORWARD; // - к следующему возможному в наборе

//  время в миллисекундах при автопереходе к слеующему вопросу
  this.autoSkipTimeout = 2000;

//  id для setTimeout
  this.autoSkipTimer = -1;

//  способ подсчёта результатов (простой и с весовыми коэффициентами)
  this.answersResultCount = QUESTION_SIMPLE_CHECK;

//  ограничение на максимальное количесвто ответов ддля одного вопроса на экране
  this.maxAnswersAllowed = -1;

//  если установлен -то в вопросе можно выбрать только один ответ (галочка будет перескакивать)
  this.answersOnlyOneSelected = false;

//  момент проверки ответов вопроса
  this.checkMode = QUESTION_CHECK_AFTER;

//  лайот
  this.answersLayout = LAYOUT_VERTICAL;
//  стартовые координаты для ответов (по умолчанию - т.е. если в конкретном
//  вопросе не заданы другие)
  this.answersX = [0];
  this.answersY = [0];

//  массив вопросов
  this.unionsArray = null; 

//  текущий вопрос (группа вопросов)
  this.questionIndex = null;
//  последовательность вопросов
  this.questionSequence = null;

//  номер текущего вопроса
  this.currentQuestionIndex = -1;

//  действия, выполняющиеся када все вопросы сичтаются отвеченными
//  т.е. имеют state != QUESTION_STATE_NOTANSWERED
  this.onAllQuestionsAnsweredActions = null;

//  Специализированные кнопки (альтернатива - генерить события в action)
  this.btnPreviousQuestion = null;
  this.btnNextQuestion = null;
  this.btnCheckAnswers = null;
  this.btnResetAnswers = null;

//  настройки счётчика вопросов
  this.counterVisible = false;
  this.counterObject = null;
  this.counterFormat = null;
  this.counterStyle = null;
  this.counterX = 0;
  this.counterY = 0;

//  настройки чекбокса
  this.checkBoxNormalBorder = null;
  this.checkBoxNormalMark = null;
  this.checkBoxDisabledBorder = null;
  this.checkBoxDisabledMark = null;

// Количество впросов на которые пользователь ответил
  this.questionsAnswered = 0;

// текущий результат выполнения задания
  this.objectResult = 0;
// варианты расцветки связующей линии
  this.relationLineNormalColor = "#000000";
  this.relationLineMarkColor = "#000000";
  this.relationLineDisabledColor = "#000000";
  this.relationLineCorrectColor = "#000000";
  
  
//  загрузка шага
  function initFromNode(srcNode) {
    var xmlNode = null;
    var xmlAttributeMap = null;
    var xmlAttribute = null;
    
    xmlAttributeMap = srcNode.attributes;
    if (xmlAttributeMap){
      xmlAttribute = xmlAttributeMap.getNamedItem("id");
      if (xmlAttribute != null && xmlAttribute.specified)
        this.id = xmlAttribute.value;
      xmlAttribute = xmlAttributeMap.getNamedItem("visible");
      if (xmlAttribute != null && xmlAttribute.specified){
        if(xmlAttribute.value == "true")
          this.visibility = OBJECT_VISIBILITY_TRUE;
        else if(xmlAttribute.value == "false")
          this.visibility = OBJECT_VISIBILITY_FALSE;
      }
      xmlAttribute = xmlAttributeMap.getNamedItem("enabled");
      if (xmlAttribute != null && xmlAttribute.specified
        && xmlAttribute.value.toLowerCase() == "false")
        this.disabled = true;
    }
    

    this.unionsArray = new Array();
    this.childObjects = new Array();
    this.loadChildsObject(srcNode);

    var srcBase = null;
    if (srcNode.ownerDocument.source){
      var tmp = new String(srcNode.ownerDocument.source).replace("/\/.g", "\\").split("\\")
      tmp.pop();
      srcBase = tmp.join("\\");
    }

    xmlNode = srcNode.firstChild;
    while(xmlNode){
      if(xmlNode.nodeName == "settings"
        || xmlNode.nodeName == "param"){

      // разбор стандартных настроек
        this.parseParamNode(xmlNode);

        var settingNode = xmlNode.firstChild;
        while(settingNode){
          if(settingNode.nodeName == "unionsPropList"){
            xmlAttributeMap = settingNode.attributes;
            if (xmlAttributeMap){
              xmlAttribute = xmlAttributeMap.getNamedItem("random");
              if (xmlAttribute != null && xmlAttribute.specified){
                if(xmlAttribute.value == "true"){
                  this.questionsRandom = true;
                } else {
                  this.questionsRandom = false;
                }
              }
              xmlAttribute = xmlAttributeMap.getNamedItem("total");
              if (xmlAttribute != null && xmlAttribute.specified){
                this.questionsToDisplay = parseInt(xmlAttribute.value);
              }
              xmlAttribute = xmlAttributeMap.getNamedItem("allowMultiple");
              if (xmlAttribute != null && xmlAttribute.specified){
                if(xmlAttribute.value == "true"){
                  this.allowMultipleAttempts = true;
                } else {
                  this.allowMultipleAttempts = false;
                }
              }
              xmlAttribute = xmlAttributeMap.getNamedItem("showCorrectRelations");
              if (xmlAttribute != null && xmlAttribute.specified){
                if(xmlAttribute.value == "true"){
                  this.showCorrectRelationsAttempts = true;
                } else {
                  this.showCorrectRelationsAttempts = false;
                }
              }
              xmlAttribute = xmlAttributeMap.getNamedItem("excludeStyle");
              if (xmlAttribute != null && xmlAttribute.specified){
                if(xmlAttribute.value == "EXCLUDE"){
                //  означает что вопросы будут исключаться из списка
                  this.excludeStyle = QUESTION_EXCLUDE;
                } else if(xmlAttribute.value == "DISABLE"){
                //  означает что вопросы будут отображаться
                //  в последнем отвеченном состоянии
                //  но будут недоступны для изменения ответов
                  this.excludeStyle = QUESTION_DISABLE;
                }
              }
              xmlAttribute = xmlAttributeMap.getNamedItem("allowSelection");
              if (xmlAttribute != null && xmlAttribute.specified){
                if(xmlAttribute.value == "false"){
                  this.allowSelection = false;
                } else {
                  this.allowSelection = true;
                }
              }
              xmlAttribute = xmlAttributeMap.getNamedItem("selectionCycling");
              if (xmlAttribute != null && xmlAttribute.specified){
                if(xmlAttribute.value == "false"){
                  this.selectionCycling = false;
                }
              }
              xmlAttribute =  xmlAttributeMap.getNamedItem("checkMode");
              if (xmlAttribute != null && xmlAttribute.specified){
                if(xmlAttribute.value == "CHECK_AFTER"){
              //  означает что проверятся ответы будт после
              // нажатия кнопки проверить
                  this.checkMode = QUESTION_CHECK_AFTER;
                } else if(xmlAttribute.value == "CHECK_IMMEDIATELY"){
              //  означает что проверятся ответы будт после первого нажатия
                  this.checkMode = QUESTION_CHECK_IMMEDIATELY;
                }
              };
            }
          } else if(settingNode.nodeName == "units"){
            xmlAttributeMap = settingNode.attributes;
            if (xmlAttributeMap){
              xmlAttribute = xmlAttributeMap.getNamedItem("answersRandom");
              if (xmlAttribute != null && xmlAttribute.specified){
                if(xmlAttribute.value == "true"){
                  this.answersRandom = true;
                } else {
                  this.answersRandom = false;
                }
              }
              xmlAttribute =  xmlAttributeMap.getNamedItem("answersLayout");
              if (xmlAttribute != null && xmlAttribute.specified){
                if(xmlAttribute.value == "LAYOUT_NO"){
                //  означает что ответы на экране будут
                //  расставлены не в столбцы или строчки,
                //  а по указанным коодинатам
                  this.answersLayout = LAYOUT_NO;
                } else if(xmlAttribute.value == "LAYOUT_VERTICAL"){
                //  означает что ответы на экране будут выстроены вертикально
                  this.answersLayout = LAYOUT_VERTICAL;
                } else if(xmlAttribute.value == "LAYOUT_HORIZONTAL"){
                //  означает что ответы на экране будут выстроены горизонтально
                  this.answersLayout = LAYOUT_HORIZONTAL;
                }
              };
              xmlAttribute = xmlAttributeMap.getNamedItem("resultMode");
              if (xmlAttribute != null && xmlAttribute.specified){
                if((xmlAttribute.value).toUpperCase() == "SIMPLE_COUNT"){
                //  простой подсчёт результатов - типа если поставлена
                //  галка не там где надо - ошибка сразу, процент 0
                  this.answersResultCount = QUESTION_SIMPLE_CHECK;
                  this.crAlgorithm = "discrete";
                } else if((xmlAttribute.value).toUpperCase()
                  == "MXK_COUNT"){
                  this.answersResultCount = QUESTION_MXK_CHECK;
                  this.crAlgorithm = "smooth_err";
                }
              }
              xmlAttribute = xmlAttributeMap.getNamedItem("onlyOneSelected");
              if (xmlAttribute != null && xmlAttribute.specified){
                if((xmlAttribute.value).toLowerCase() == "true"){
                  //this.answersOnlyOneSelected = true;
                } else if((xmlAttribute.value).toLowerCase() == "auto"){
                  //this.answersOnlyOneSelected = "auto";
                } else {
                  //this.answersOnlyOneSelected = false;
                }
              }
              xmlAttribute = xmlAttributeMap.getNamedItem("maxAllowed");
              if (xmlAttribute != null && xmlAttribute.specified){
                this.maxAnswersAllowed = parseInt(xmlAttribute.value);
              }
              xmlAttribute = xmlAttributeMap.getNamedItem("answersX");
              if (xmlAttribute != null && xmlAttribute.specified){
                //this.answersX = parseInt(xmlAttribute.value);
                this.answersX = (xmlAttribute.value).split(",");
              }
              xmlAttribute = xmlAttributeMap.getNamedItem("answersY");
              if (xmlAttribute != null && xmlAttribute.specified){
                //this.answersY = parseInt(xmlAttribute.value);
                this.answersY = (xmlAttribute.value).split(",");
              }
            }
          } else if(settingNode.nodeName == "counter"){
            xmlAttributeMap = settingNode.attributes;
            if (xmlAttributeMap){
              this.counterVisible = true;
              xmlAttribute =  xmlAttributeMap.getNamedItem("format");
              if (xmlAttribute != null && xmlAttribute.specified){
                this.counterFormat = xmlAttribute.value;
              };
              xmlAttribute = xmlAttributeMap.getNamedItem("style");
              if (xmlAttribute != null && xmlAttribute.specified){
                this.counterStyle = xmlAttribute.value;
              }
              xmlAttribute = xmlAttributeMap.getNamedItem("x");
              if (xmlAttribute != null && xmlAttribute.specified){
                this.counterX = parseInt(xmlAttribute.value);
              }
              xmlAttribute = xmlAttributeMap.getNamedItem("y");
              if (xmlAttribute != null && xmlAttribute.specified){
                this.counterY = parseInt(xmlAttribute.value);
              }
            }
          } else if(settingNode.nodeName == "autoskip"){
            xmlAttributeMap = settingNode.attributes;
            if (xmlAttributeMap){
              this.autoSkip = true;
              xmlAttribute =  xmlAttributeMap.getNamedItem("direction");
              if (xmlAttribute != null && xmlAttribute.specified){
                switch(xmlAttribute.value){
                case "FORWARD":
                  this.autoSkipDirection = QUESTION_AUTOSKIP_FORWARD;
                  break;
                case "BACK":
                  this.autoSkipDirection = QUESTION_AUTOSKIP_BACK;
                  break;
                case "RANDOM":
                  this.autoSkipDirection = QUESTION_AUTOSKIP_RANDOM;
                  break;
                }
              };
              xmlAttribute = xmlAttributeMap.getNamedItem("timeout");
              if (xmlAttribute != null && xmlAttribute.specified){
                this.autoSkipTimeout = parseInt(xmlAttribute.value);
              }
            }
          } else if(settingNode.nodeName == "checkbox"){
            xmlAttributeMap = settingNode.attributes;
            if (xmlAttributeMap){
              xmlAttribute =  xmlAttributeMap.getNamedItem("normalBorder");
              if (xmlAttribute != null && xmlAttribute.specified){
                this.checkBoxNormalBorder =
                  scene.Utils.makePathSrc(srcBase, xmlAttribute.value);
              };
              xmlAttribute = xmlAttributeMap.getNamedItem("normalMark");
              if (xmlAttribute != null && xmlAttribute.specified){
                this.checkBoxNormalMark =
                  scene.Utils.makePathSrc(srcBase, xmlAttribute.value);
              }
              xmlAttribute = xmlAttributeMap.getNamedItem("disabledBorder");
              if (xmlAttribute != null && xmlAttribute.specified){
                this.checkBoxDisabledBorder =
                  scene.Utils.makePathSrc(srcBase, xmlAttribute.value);
              }
              xmlAttribute = xmlAttributeMap.getNamedItem("disabledMark");
              if (xmlAttribute != null && xmlAttribute.specified){
                this.checkBoxDisabledMark =
                  scene.Utils.makePathSrc(srcBase, xmlAttribute.value);
              }
            }
          } else if(settingNode.nodeName == "relationLine"){
            xmlAttributeMap = settingNode.attributes;
            if (xmlAttributeMap){
              xmlAttribute =  xmlAttributeMap.getNamedItem("normalColor");
              if (xmlAttribute != null && xmlAttribute.specified){
                this.relationLineNormalColor =xmlAttribute.value;
              }
              xmlAttribute =  xmlAttributeMap.getNamedItem("markColor");
              if (xmlAttribute != null && xmlAttribute.specified){
                this.relationLineMarkColor =xmlAttribute.value;
              }
              xmlAttribute =  xmlAttributeMap.getNamedItem("disabledColor");
              if (xmlAttribute != null && xmlAttribute.specified){
                this.relationLineDisabledColor =xmlAttribute.value;
              }
              xmlAttribute =  xmlAttributeMap.getNamedItem("correctColor");
              if (xmlAttribute != null && xmlAttribute.specified){
                this.relationLineCorrectColor =xmlAttribute.value;
              }
            }
          }
          settingNode = settingNode.nextSibling;
        }
      } else if(xmlNode.nodeName == "unions"){
        var questionNode = xmlNode.firstChild;
        while(questionNode){
          if(questionNode.nodeName == "union"){
            var newObject = new Composition();
            newObject._class = "union_singleUnion";
            newObject.parent = this;
            newObject.crAlgorithm = this.crAlgorithm;
          //  устанавливаем св-ва вопроса по умолчанию ----
            newObject.answersResultCount = this.answersResultCount;
            newObject.excludeStyle = this.excludeStyle;
            newObject.allowMultipleAttempts = this.allowMultipleAttempts;
            newObject.showCorrectRelationsAttempts = this.showCorrectRelationsAttempts;
            newObject.maxAnswersAllowed = this.maxAnswersAllowed;
            newObject.answersOnlyOneSelected = this.answersOnlyOneSelected;
            newObject.checkMode = this.checkMode;
            newObject.answersRandom = this.answersRandom;
            newObject.answersLayout = this.answersLayout;
            newObject.answersX = this.answersX;
            newObject.answersY = this.answersY;
            
            newObject.checkBoxNormalBorder = this.checkBoxNormalBorder;
            newObject.checkBoxNormalMark = this.checkBoxNormalMark;
            newObject.checkBoxDisabledBorder = this.checkBoxDisabledBorder;
            newObject.checkBoxDisabledMark = this.checkBoxDisabledMark;
            newObject.relationLineNormalColor = this.relationLineNormalColor;
            newObject.relationLineMarkColor = this.relationLineMarkColor;
            newObject.relationLineDisabledColor = this.relationLineDisabledColor;
            newObject.relationLineCorrectColor = this.relationLineCorrectColor;
          //  ---------------------------------------------
            newObject.visible = false;
            if(newObject.initFromNode(questionNode)){
              this.unionsArray.push(newObject);
            } else {
              newObject.parent = null;
              newObject = null;
            }
          }
          questionNode = questionNode.nextSibling;
        }
      } else if(xmlNode.nodeName == "actions"){
        this.parseActionsNode(xmlNode);
        this.onAllQuestionsAnsweredActions =
          scene.Utils.parseActionsNode(xmlNode, "onAllQuestionAnswered");
      } else if(xmlNode.nodeName == "effects"){
        this.parseEffectsNode(xmlNode);
      } else if(xmlNode.nodeName == "objectives"){
        this.parseObjectivesNode(xmlNode);
      } else if(xmlNode.nodeName == "conditions"){
        var conditionNode = xmlNode.firstChild;
        while(conditionNode){
          if(conditionNode.nodeName == "condition"){
            this.parseConditionNode(conditionNode);
          }
          conditionNode = conditionNode.nextSibling;
        }
        this.parseConditionNode(xmlNode);
      }
      xmlNode = xmlNode.nextSibling;
    }

  //  поиск кнопок с соответствующимим id и установка callback'ов
    for(var i = 0; i < this.childObjects.length; i++){
      if(this.childObjects[i].type == "rnmc_stdButton"){
        switch(this.childObjects[i].id){
        case "btnPreviousQuestion":
        //  надобность этого мягко говоря под вопросом
          this.btnPreviousQuestion = this.childObjects[i];
          this.childObjects[i].setReleaseCallBack(this, this.buttonDispatcher);
          break;
        case "btnNextQuestion":
        //  надобность этого мягко говоря под вопросом
          this.btnNextQuestion = this.childObjects[i];
          this.childObjects[i].setReleaseCallBack(this, this.buttonDispatcher);
          break;
        case "btnCheck":
        //  надобность этого мягко говоря под вопросом
          this.btnCheckAnswers = this.childObjects[i];
          this.childObjects[i].setReleaseCallBack(this, this.buttonDispatcher);
          break;
        case "btnReset":
        //  надобность этого мягко говоря под вопросом
          this.btnResetAnswers = this.childObjects[i];
          this.childObjects[i].setReleaseCallBack(this, this.buttonDispatcher);
          break;
        }
      }
    }
    if(this.counterVisible){
      this.counterObject = new Text();
      this.counterObject.parent = this;
      this.counterObject.visible = true;
      this.counterObject.x = this.counterX;
      this.counterObject.y = this.counterY;
      if(this.counterStyle){
        this.counterObject.style = this.counterStyle;
      }
    }
    return true;
  }

  function showObject(){
  //  для объекта question
    this.questionSequence = new Array();
    if(this.questionsRandom){
  // random
      var tempSequence = new Array();
      for(var i = 0; i < this.unionsArray.length; i++)
        tempSequence.push(i);
      if(this.questionsToDisplay > 0){
        this.questionSequence =
          scene.Utils.permutateArray(tempSequence, this.questionsToDisplay);
      } else {
        this.questionSequence =
          scene.Utils.permutateArray(tempSequence);
      }
    } else {
      if(this.questionsToDisplay > 0)
        for(var i = 0; i < this.unionsArray.length
          && i < this.questionsToDisplay; i++)
          this.questionSequence.push(i);
      else
        for(var i = 0; i < this.unionsArray.length; i++)
          this.questionSequence.push(i);
    }

    if(this.allowSelection){
      if(this.btnPreviousQuestion && this.questionSequence.length > 1){
        this.btnPreviousQuestion.showObject();
      }
      if(this.btnNextQuestion && this.questionSequence.length > 1){
        this.btnNextQuestion.showObject();
      }
    }

    if ( this.autoSkip && this.autoSkipDirection == QUESTION_AUTOSKIP_RANDOM){
      var notAnsweredQuestions = new Array();
      for(var i = 0; i < this.questionSequence.length; i++){
        if(this.unionsArray[this.questionSequence[i]].objectState == QUESTION_STATE_NOTANSWERED){
          notAnsweredQuestions.push(i);
        }
      }
      if(notAnsweredQuestions.length > 0){
        var questionIndex = Math.round(Math.random()*notAnsweredQuestions.length - 0.5);
        this.showQuestion(notAnsweredQuestions[questionIndex]);
      }
    } else {
      this.showQuestion(0);
    }
    
    rnmc_stdMediaGroup_showObject();
    this.btnCheckAnswers.hideObject();
  }

  function hideObject(){
    rnmc_stdMediaGroup_hideObject();
  }

// отображение счетчика вопросов
  function updateCounter(){ 
    if(this.counterVisible && this.counterObject){
      if(this.counterFormat){
        var str = this.counterFormat.slice(0);
        str = str.replace(/%total%/g, this.questionSequence.length);
        str = str.replace(/%elapsed%/g, this.questionsAnswered); //this.currentQuestionIndex + 1);
        str = str.replace(/%number%/g, this.currentQuestionIndex + 1);
        str = str.replace(/%remaining%/g, (this.questionSequence.length - this.questionsAnswered));
        this.counterObject.value = str;
      } else {
        this.counterObject.visible = false;
      }
    }
  }

// отображение вопроса по индексу
  function showQuestion(questionIndex){
    if(questionIndex >= 0 && questionIndex < this.questionSequence.length){
      if(this.currentQuestionIndex >= 0){
        this.unionsArray[this.questionSequence[this.currentQuestionIndex]].hideObject();
      }
      this.currentQuestionIndex = questionIndex;

    //===========================================================
      if(!this.selectionCycling){
      //  если нет зацикливания набора вопросов
      //    - то управляем кнопками вперёд/назад здесь
        var questionsBeforeCurrent = 0;
        var questionsAfterCurrent = 0;
        if(!this.allowMultipleAttempts && this.excludeStyle == QUESTION_EXCLUDE){
          for(var i = 0; i < this.questionSequence.length; i++){
            if(this.unionsArray[this.questionSequence[i]].objectState == QUESTION_STATE_NOTANSWERED){
              if(i < this.currentQuestionIndex){
                questionsBeforeCurrent++;
              } else if(i > this.currentQuestionIndex){
                questionsAfterCurrent++;
              }
            }
          }
        } else {
          for(var i = 0; i < this.questionSequence.length; i++){
            if(i < this.currentQuestionIndex){
              questionsBeforeCurrent++;
            } else if(i > this.currentQuestionIndex){
              questionsAfterCurrent++;
            }
          }
        }
        if(questionsBeforeCurrent == 0){
          if(this.btnPreviousQuestion){
            this.btnPreviousQuestion.hideObject();
          }
        } else {
          if(this.btnPreviousQuestion){
            this.btnPreviousQuestion.showObject();
          }
        }
        if(questionsAfterCurrent == 0){
          if(this.btnNextQuestion){
            this.btnNextQuestion.hideObject();
          }  
        } else {
          if(this.btnNextQuestion){
            this.btnNextQuestion.showObject();
          }
        }
      }
    //===========================================================

      this.updateCounter();
      if(this.checkMode == QUESTION_CHECK_AFTER){
        if(this.unionsArray[this.questionSequence[this.currentQuestionIndex]].allowMultipleAttempts
          || this.unionsArray[this.questionSequence[this.currentQuestionIndex]].objectState == QUESTION_STATE_NOTANSWERED){
          if(this.btnCheckAnswers)
            //this.btnCheckAnswers.showObject();
          if(this.btnResetAnswers )
            this.btnResetAnswers.showObject();
        } else {
          if(this.btnCheckAnswers)
            this.btnCheckAnswers.hideObject();
          if(this.btnResetAnswers )
            this.btnResetAnswers.hideObject();
        }
      }
      this.unionsArray[this.questionSequence[this.currentQuestionIndex]].showObject();
    }
  }

  function previousQuestion(){
  //  сначала очищаем autoskip timeout, а то если человек уже
  //  перешёл к другому вопросу (если есть возмжность выбора) - будет кисло
    try{
      this.clearTimeout(this.autoSkipTimer);
    }
    catch(ex){
      trace("#FF0000Error: " + ex);
    }
    var i = this.currentQuestionIndex;
    while(true){
      if(i == 0){
        i = this.questionSequence.length - 1;
      } else {
        i--;
      };
      if(i == this.currentQuestionIndex){
        break;
      } else {
        if(this.allowMultipleAttempts){
        //  можно отвечать на один и тот же вопрос несколько раз
          this.showQuestion(i);
          break;
        } else {
          if(this.unionsArray[this.questionSequence[i]].objectState == QUESTION_STATE_ANSWERED){
            if(this.excludeStyle == QUESTION_DISABLE){
              this.showQuestion(i);
              break;
            }
          } else {
            this.showQuestion(i);
            break;
          };
        };
      };
    };
  }

  function nextQuestion(){
  //  сначала очищаем autoskip timeout, а то если человек уже
  //  перешёл к другому вопросу (если есть возмжность выбора) - будет ошибка
    try{
      this.clearTimeout(this.autoSkipTimer);
    }
    catch(ex){
      trace("#FF0000Error: " + ex);
    }
    var i = this.currentQuestionIndex;
    while(true){
      if(i == this.questionSequence.length - 1){
        i = 0;
      } else {
        i++;
      };
      if(i == this.currentQuestionIndex){
        break;
      } else {
        if(this.allowMultipleAttempts){
        //  можно отвечать на один и тот же вопрос несколько раз
          this.showQuestion(i);
          break;
        } else {
          if(this.unionsArray[this.questionSequence[i]].objectState == QUESTION_STATE_ANSWERED){
            if(this.excludeStyle == QUESTION_DISABLE){
              this.showQuestion(i);
              break;
            }
          } else {
            this.showQuestion(i);
            break;
          };
        };
      };
    };
  }

//  обновляет текущее состояние статистики - шоб 
//  даже если прервали - то посчиталось
  function updateStepResult(){
    var totalQuestions = 0;
    var totalPercents = 0;
    for(var i = 0; i < this.questionSequence.length; i++){
      if(this.unionsArray[this.questionSequence[i]].objectState == QUESTION_STATE_ANSWERED){
        totalPercents += this.unionsArray[this.questionSequence[i]].currentResult;
        totalQuestions++;
      } else {
        totalQuestions++;
      }
    }
    this.objectResult = Math.round(totalPercents/totalQuestions);
  }

  function notifyQuestionAnswered(newResult, annotationText){
    var notAnsweredQuestions = 0;
    this.updateStepResult();
    if(!this.allowMultipleAttempts){
      if(this.btnCheckAnswers){
        this.btnCheckAnswers.hideObject();
      }
      if(this.btnResetAnswers){
        this.btnResetAnswers.hideObject();
      }
    }
    scene.Labwork.addNewResult(newResult, annotationText);
    for(var i = 0; i < this.questionSequence.length; i++){
      if(this.unionsArray[this.questionSequence[i]].objectState == QUESTION_STATE_NOTANSWERED){
        notAnsweredQuestions++;
      }
    }

  // Подсчитать количество заданий (вопросов) на которые пользователь не ответил
    this.questionsAnswered = this.questionSequence.length - notAnsweredQuestions;

  // Обновить счетчики
    updateCounter();

  //  если ответили на все вопросы - выполняем необходимые действия
    if(notAnsweredQuestions == 0){
      if(this.autoSkip){
        this.autoSkipTimer = this.setTimeout("this.onAnsweredQuestionsTimeout()", this.autoSkipTimeout);
      }
      else {
        if(this.onAllQuestionsAnsweredActions){
          for(var i = 0; i < this.onAllQuestionsAnsweredActions.length; i++){
            this.dispatchAction(this.onAllQuestionsAnsweredActions[i]);
          }
        }
      }
    } else {
      if(this.autoSkip){
        if(notAnsweredQuestions == 1 && this.selectionCycling){
          if(this.btnPreviousQuestion){
            this.btnPreviousQuestion.hideObject();
          }
          if(this.btnNextQuestion){
            this.btnNextQuestion.hideObject();
          }
        }
      //  если необходимо автоматиечски перейти к следующему вопросу
        this.autoSkipTimer = this.setTimeout("this.onAutoSkipTimeout()", this.autoSkipTimeout);
      }
    }
  }

//  обработчик таймера завершения ответа на все вопросы, если включен автоперехода к другому вопросу  
  function onAnsweredQuestionsTimeout() {
    if(!this.autoSkip)
      return;

    if(this.onAllQuestionsAnsweredActions){
      for(var i = 0; i < this.onAllQuestionsAnsweredActions.length; i++){
        this.dispatchAction(this.onAllQuestionsAnsweredActions[i]);
      }
    }
  }

//  обработчик таймера втоперехода к другому вопросу
  function onAutoSkipTimeout(){
    if(!this.autoSkip)
      return;

    switch(this.autoSkipDirection){
    case QUESTION_AUTOSKIP_FORWARD:  
      this.nextQuestion();
      break;
    case QUESTION_AUTOSKIP_BACK:
      this.previousQuestion();
      break;
    case QUESTION_AUTOSKIP_RANDOM:
      var notAnsweredQuestions = new Array();
      for(var i = 0; i < this.questionSequence.length; i++){
        if(this.unionsArray[this.questionSequence[i]].objectState == QUESTION_STATE_NOTANSWERED){
          notAnsweredQuestions.push(i);
        }
      }
      if(notAnsweredQuestions.length > 0){
        var questionIndex = Math.round(Math.random()*notAnsweredQuestions.length - 0.5);
        this.showQuestion(notAnsweredQuestions[questionIndex]);
      }
      break;
    }
  }

  function buttonDispatcher(btnId){
      switch(btnId){
    case "btnPreviousQuestion":
      if(this.allowSelection)
        this.previousQuestion();
      break;
    case "btnNextQuestion":
      if(this.allowSelection)
        this.nextQuestion();
      break;
    case "btnCheck":
    //  проверка ответов
      this.unionsArray[this.questionSequence[this.currentQuestionIndex]].resetAnswers();    
      this.unionsArray[this.questionSequence[this.currentQuestionIndex]].checkAnswers();
      break;
    case "btnReset":
    //  сброс ответов
      this.unionsArray[this.questionSequence[this.currentQuestionIndex]].resetAnswers();
      this.unionsArray[this.questionSequence[this.currentQuestionIndex]].destroyRelationLines();
      for(var j = 0; j < this.unionsArray[this.questionSequence[this.currentQuestionIndex]].childObjects.length; j++){
        if(this.unionsArray[this.questionSequence[this.currentQuestionIndex]].childObjects[j].type == "rnmc_stdCheckBox"){
          this.unionsArray[this.questionSequence[this.currentQuestionIndex]].childObjects[j].enableObject();
        }
      }
      break;
      }
  }

  function getResult(resultsArray){
    if(resultsArray && this.crAlgorithm != "none"){
      // Собирем статистику со все вопросов
      var totalQuestions = 0;
      var totalPercents = 0;
      
      for(var i = 0; i < this.questionSequence.length; i++){
        totalPercents += this.unionsArray[this.questionSequence[i]].getResult();
        totalQuestions++;
      }
      
      this.objectResult = Math.round(totalPercents/totalQuestions);
      
      var resultString = this.objectResult + ";1.0";
      resultsArray.push(resultString);
    }

    rnmc_stdMediaGroup_getResult(resultsArray);    
  } 

  function dispatchAction(singleAction){

      rnmc_stdMediaGroup_dispatchAction(singleAction);
  }



  
]]></script>
</composition>

<composition name="union_singleUnion" class="rnmc_stdMediaGroup">
<script><![CDATA[
//  состояние
  this.objectState = QUESTION_STATE_NOTANSWERED;
  this.questionDisabled = false;
//  текущий результат для данного конкретного вопроса
  this.currentResult = 0;
  this.currentErrors = 0;
  this.attemptsCount = 0;
  // false если последнее соотношение было ошибочным
  this.lastRelation = null;
  // данное свойство изменяется на true, если все положительные 
  // соотношения в выборе по одному установлены
  this.checkImmediatelyComplete = false;
//  вывод ответов в произвольном порядке или в том котором в файле
  this.answersRandom = false;
//  режим 'отключения' вопроса. QUESTION_EXCLUDE - исключает вопрос из набора вопросов
//  QUESTION_DISABLED - вопрос после отвечания доступен только для просмотра
  this.excludeStyle = QUESTION_EXCLUDE;
//  возможность повторного ответа на данный вопрос
//  если true - можно отвечать до посинения, при этом результатом
//  для данного вопроса считается последний результат
  this.allowMultipleAttempts = true;
// запрещено показывать правильные оптношения
  this.showCorrectRelationsAttempts = false;
//  способ подсчёта результатов для конкретного вопроса может отличатся
//  от принятого по умолчанию (простой или с весовыми коэффициентами)
//  this.answersResultCount = QUESTION_MXK_CHECK;
//  this.answersResultCount = QUESTION_USE_WEIGHTS_CHECK;
  this.answersResultCount = QUESTION_SIMPLE_CHECK;
//  режим проверки ответов - 
  this.checkMode = QUESTION_CHECK_AFTER;

//  ограничение на максимальное количесвто ответов для одного вопроса на экране
  this.maxAnswersAllowed = -1;
//  для объекта Union значение данного параметра предполагает состояние falce однозначно,
//  так как для проведения одной линии всегда необходимо наличие двух объектов (чекбоксов)
  this.answersOnlyOneSelected = false;

//  координаты и стиль вывода ответов
  this.answersStartX = -1;
  this.answersStartY = -1;
  this.answerAlign = "QUESTION_ANSWERALIGN_DOWN";

//  настройки чекбокса
  this.checkBoxNormalBorder = null;
  this.checkBoxNormalMark = null;
  this.checkBoxDisabledBorder = null;
  this.checkBoxDisabledMark = null;

//  массив ответов
  this.answersArray = null;
//  последовательность вывода ответов на экран
  this.answersSequence = null;
  this.rightAnswers = 0;

//координаты ответов
  this.startAnswerX = 50;
  this.startAnswerY = 100;

//  переменные для сохранения состояния ответов (если нужна
//  блокировка повторного ответа например)
//  последовательновательность ответов на экране
  this.lastAnswersSequence = null;
//  последовательность галочек (отмечено - 1, неотмечено - 0)
  this.lastCheckedSequence = null;

//  =================================================================
//  действия, специфичные для отдельного вопроса
//  действия - если соответствия расставлены верно
this.resultRightActions = null;
//  действия - если соответствия расставлены неверно
this.resultWrongActions = null;
//  действия - если результат ответа ниже порогового значения 
this.answeredBelowResultActions = null;
//  действия - если результат ответа выше порогового значения 
this.answeredAboveResultActions = null;
//  действия - если результат ответа находицца между двумя значенимя в формате "нижн;верхн"
this.answeredBetweenResultsActions = null;
// действие если выбрано одно правильное соотношение
this.rightRelationActions = null;
// действие если выбрано одно неправильное соотношение
this.wrongRelationActions = null;
// действия при проверке одного соотношения
this.relationActions = null;
// действия - если все связи установлены
this.resultCompleteActions = null;
// действия - если первое отношение было установлено
this.firstRelationCheckedActions = null;
// действия, выполняемые при выходе курсора из чекбокса
this.finishOperationActions = null;
// ======================================================================
//  массив имен множеств
  this.unionsName = null;
//  число множеств
    this.unionsCount = 0;
//  массив количества элементов по каждому множеству
    this.unionsUnitsCountArray = null;
//  количество определенных (targetsId="answ1_t,answ3_t") отношений по каждому множеству
  this.rightUnionsUnitsRelationsArr = null;
//  общее количество отношений
  this.relationsCount = 0;
//  список (массив) стилей, указывающий на положение чекбокса по отношению к объекту для какждого множества
  this.autoAttachStyles = null;
// ======================================================
//  имя множества выбранного в данный момент элемента
  this.currentUnionName = "";
  //this.currentRelationObj = null;
  this.currentObjId = "";
  this.relationsAray = new Array();
  
// ======================================
// варианты расцветки связующей линии
  this.relationLineNormalColor = null;
  this.relationLineMarkColor = null;
  this.relationLineDisabledColor = null;
  this.relationLineCorrectColor = null;
  
  function initFromNode(srcNode){
    var xmlNode = null;
    var xmlAttributeMap = null;
    var xmlAttribute = null;

    this.childObjects = new Array();
    this.answersArray = new Array();
    this.loadChildsObject(srcNode);

    xmlAttributeMap = srcNode.attributes;
    if (xmlAttributeMap){
      xmlAttribute = xmlAttributeMap.getNamedItem("id");
      if (xmlAttribute != null && xmlAttribute.specified)
        this.id = xmlAttribute.value;
    }

    xmlNode = srcNode.firstChild;
    while(xmlNode){
      if(xmlNode.nodeName == "param"){
        xmlAttributeMap = xmlNode.attributes;
        if (xmlAttributeMap){
          xmlAttribute =  xmlAttributeMap.getNamedItem("x");
          if (xmlAttribute != null && xmlAttribute.specified)
            this.x = parseInt(xmlAttribute.value);
          xmlAttribute =  xmlAttributeMap.getNamedItem("y");
          if (xmlAttribute != null && xmlAttribute.specified)
            this.y = parseInt(xmlAttribute.value);

          xmlAttribute = xmlAttributeMap.getNamedItem("answersRandom");
          if (xmlAttribute != null && xmlAttribute.specified){
            if(xmlAttribute.value == "true"){
              //  настройка перемешивания ответов для данного вопроса
              this.answersRandom = true;    //  перемешиваем
            } else {
              this.answersRandom = false;    //  не перемешиваем
            }
          }
          xmlAttribute =  xmlAttributeMap.getNamedItem("answerLayout");
          if (xmlAttribute != null && xmlAttribute.specified){
            if(xmlAttribute.value == "LAYOUT_NO"){
            //  означает что ответы на экране будут расставлены не в столбцы или строчки,
            //  а по указанным коодинатам
              this.answersLayout = LAYOUT_NO;
            } else if(xmlAttribute.value == "LAYOUT_VERTICAL"){
            //  означает что ответы на экране будут выстроены вертикально
              this.answersLayout = LAYOUT_VERTICAL;
            } else if(xmlAttribute.value == "LAYOUT_HORIZONTAL"){
            //  означает что ответы на экране будут выстроены горизонтально
              this.answersLayout = LAYOUT_HORIZONTAL;
            }
          };
          xmlAttribute = xmlAttributeMap.getNamedItem("allowMultiple");
          if (xmlAttribute != null && xmlAttribute.specified){
            if(xmlAttribute.value == "true"){
              this.allowMultipleAttempts = true;
            } else {
              this.allowMultipleAttempts = false;
            }
          } 
          xmlAttribute = xmlAttributeMap.getNamedItem("showCorrectRelations");
          if (xmlAttribute != null && xmlAttribute.specified){
            if(xmlAttribute.value == "true"){
              this.showCorrectRelationsAttempts = true;
            } else {
              this.showCorrectRelationsAttempts = false;
            }
          } 
          xmlAttribute = xmlAttributeMap.getNamedItem("maxAllowed");
          if (xmlAttribute != null && xmlAttribute.specified){
            this.maxAnswersAllowed = parseInt(xmlAttribute.value);
          }
          xmlAttribute = xmlAttributeMap.getNamedItem("onlyOneSelected");
          // данный элемент зарезервирован за сервисом, позволяющим 
          // назначать выбор отношения 1 к 1 ("true"), или многое ко многому ("falce")
          if (xmlAttribute != null && xmlAttribute.specified){
            if((xmlAttribute.value).toLowerCase() == "true"){
              //this.answersOnlyOneSelected = true;              
            } else if((xmlAttribute.value).toLowerCase() == "auto"){
              //this.answersOnlyOneSelected = "auto";
              //
            } else {
              //this.answersOnlyOneSelected = false;
            }
          }
          xmlAttribute = xmlAttributeMap.getNamedItem("answersX");
          if (xmlAttribute != null && xmlAttribute.specified){
            //this.answersX = parseInt(xmlAttribute.value);
            this.answersX = (xmlAttribute.value).split(",");            
          }
          xmlAttribute = xmlAttributeMap.getNamedItem("answersY");
          if (xmlAttribute != null && xmlAttribute.specified){
            //this.answersY = parseInt(xmlAttribute.value);
            this.answersY = (xmlAttribute.value).split(",");
          }
          xmlAttribute = xmlAttributeMap.getNamedItem("unionsName");
          if (xmlAttribute != null && xmlAttribute.specified){
            this.unionsName = (xmlAttribute.value).split(",");
            this.unionsCount = this.unionsName.length;
            this.unionsUnitsCountArray = new Array(this.unionsCount);
            this.rightUnionsUnitsRelationsArr = new Array(this.unionsCount);
            for(var n=0; n<this.unionsCount; n++){
              this.rightUnionsUnitsRelationsArr[n] = 0;
            }
          }
          xmlAttribute = xmlAttributeMap.getNamedItem("autoAttachStyles");
          if (xmlAttribute != null && xmlAttribute.specified){
            this.autoAttachStyles = (xmlAttribute.value).split(",");
          }          
          xmlAttribute =  xmlAttributeMap.getNamedItem("checkMode");
          if (xmlAttribute != null && xmlAttribute.specified){
            if(xmlAttribute.value == "CHECK_AFTER"){
            //  означает что проверятся ответы будт после нажатия кнопки проверить
              this.checkMode = QUESTION_CHECK_AFTER;
            } else if(xmlAttribute.value == "CHECK_IMMEDIATELY"){
            //  означает что проверятся ответы будт после первого нажатия
              this.checkMode = QUESTION_CHECK_IMMEDIATELY;
            }
          };
        }
      } else if(xmlNode.nodeName == "unit"){
      //  инициализация объекта "ответ"
        var newObject = new Composition();
        newObject._class = "union_singleAnswer";
        newObject.parent = this;
        newObject.visible = true;
        if(newObject.initFromNode(xmlNode)){
        //  заполнение массива соответствия целевых объектов
          if (this.unionsCount >1){
            newObject.unionNum = scene.Utils.getOne(newObject.unionName, this.unionsName);
            this.incrementRelCounter(newObject.unionNum);
          } else {
            newObject.unionNum = 0;
          }            
        //  создаётся чекбокс, который стандартными аттач-методами
        //  крепится к объекту
          var checkBox = new Composition();
          checkBox._class = "rnmc_stdCheckBox";
          checkBox.parent = this;
          checkBox.visible = false;
        //  установка св-в чекбокса, необходимых для отображения
          checkBox.id = "chkBox_" + newObject.id;
          checkBox.boxSrcNormal = this.checkBoxNormalBorder;
          checkBox.markSrcNormal = this.checkBoxNormalMark;
          checkBox.boxSrcDisabled = this.checkBoxDisabledBorder;
          checkBox.markSrcDisabled = this.checkBoxDisabledMark;
          checkBox.autoAttachTarget = newObject.id;
          checkBox.visibility = OBJECT_VISIBILITY_TRUE;
          //checkBox.autoAttachStyle = AUTOATTACH_LEFT_CENTER;
          if (this.unionsCount >0){
            var theStr = this.autoAttachStyles[newObject.unionNum];
            var theAttachStyle = scene.Utils.getAutoAttachStyle(theStr);
            checkBox.autoAttachStyle = theAttachStyle;
          } else {
            checkBox.autoAttachStyle = AUTOATTACH_LEFT_CENTER;
          }
          checkBox.autoAttachOffsetX = 30;
          checkBox.autoAttachOffsetY = 0;
          checkBox.setPressCallBack(newObject, newObject.onCheckBoxChanged);
          checkBox.setRollOutCallBack(newObject, newObject.onRollOutCheckBox);
          newObject.checkBox = checkBox;
        //  
          if (this.unionsCount > 0){
            this.rightUnionsUnitsRelationsArr[newObject.unionNum] += newObject.targetsCount;
          }
        //  
          /*
          this.answersTotal++;
          if(newObject.rightAnswer){
            this.rightAnswers++;
          } else {
            this.wrongAnswers++;
          }
          if(this.maxAnswersAllowed > 0 && this.rightAnswers > this.maxAnswersAllowed){
            trace("#FF0000Ошибка: число правильных ответов больше чем всего разрешено.");
          }
          */
          this.answersArray.push(newObject);
          this.childObjects.push(newObject);
          this.childObjects.push(checkBox);
        } else {
          newObject.parent = null;
          newObject = null;
        }
      } else if(xmlNode.nodeName == "actions"){
        this.parseActionsNode(xmlNode);
      //  действия - если отвечен верно
        this.resultRightActions = scene.Utils.parseActionsNode(xmlNode, "onResultRight");
      //  действия - если отвечен неверно
        this.resultWrongActions = scene.Utils.parseActionsNode(xmlNode, "onResultWrong");
      //  действия - если результат ответа ниже порогового значения 
        this.answeredBelowResultActions = scene.Utils.parseActionsNode(xmlNode, "onResultBelow");
      //  действия - если результат ответа выше порогового значения 
        this.answeredAboveResultActions = scene.Utils.parseActionsNode(xmlNode, "onResultAbove");
      //  действия - если результат ответа находицца между двумя значенимя в формате "нижн;верхн"
        this.answeredBetweenResultsActions = scene.Utils.parseActionsNode(xmlNode, "onResultBetween");
      // действия если все соотношения были установлены
        this.resultCompleteActions = scene.Utils.parseActionsNode(xmlNode, "onResultComplete");
      // действия если первое соотношение было установлено
      //  this.firstRelationCheckedActions = scene.Utils.parseActionsNode(xmlNode, "onFirstRelationChecked");
      // действие если выбрано одно правильное соотношение
        this.rightRelationActions = scene.Utils.parseActionsNode(xmlNode, "onRightRelation");
      // действие если выбрано одно неправильное соотношение
        this.wrongRelationActions = scene.Utils.parseActionsNode(xmlNode, "onWrongRelation");
      // действие на установленное отношение
        this.relationActions = scene.Utils.parseActionsNode(xmlNode, "onRelation");
      // действия, выполняемые при выходе курсора из чекбокса
        this.finishOperationActions = scene.Utils.parseActionsNode(xmlNode, "onFinishOperation");
      }
      xmlNode = xmlNode.nextSibling;
    }
    
    //if (this.answersOnlyOneSelected = "auto" ) {
      //this.answersOnlyOneSelected = this.rightAnswers > 1 ? false : true;
    //} 
    // если удачно  инициализированно
    return true;
  }
  

  function showObject(){
    var originalSequence = new Array();
    if(this.allowMultipleAttempts || this.objectState == QUESTION_STATE_NOTANSWERED){
    //  если на этот вопрос можно отвечать повторно  
      if(this.answersRandom){
        if(this.maxAnswersAllowed > 0){
        //  значит есть ограничение на количество ответов
          var answersSelected = 0;
          var tempSequence = new Array();

          for(var i = 0; i < this.answersArray.length; i++)
            tempSequence.push(i);
            originalSequence.push(i);
          var permutatedSequence = scene.Utils.permutateArray(tempSequence);  
          
          tempSequence = new Array();
          for(var i = 0; i < permutatedSequence.length; i++){
            if(this.answersArray[permutatedSequence[i]].rightAnswer){
              tempSequence.push(permutatedSequence[i]);
              answersSelected++;
            }
          }
          
          for(var i = 0; i < permutatedSequence.length && answersSelected < this.maxAnswersAllowed; i++){
            if(!this.answersArray[permutatedSequence[i]].rightAnswer){
              answersSelected++;
              tempSequence.push(permutatedSequence[i]);
            }
          }

          this.answersSequence = scene.Utils.permutateArray(tempSequence, tempSequence.length);
              
        } else {
        //  нет ограничений на количество ответов
          var tempSequence = new Array();
          for(var i = 0; i < this.answersArray.length; i++){
            tempSequence.push(i);
            originalSequence.push(i);
          }
          this.answersSequence = scene.Utils.permutateArray(tempSequence, tempSequence.length);
        }
      } else {          //  если не надо перемешивать ответы
        if(this.maxAnswersAllowed > 0){
          var answersSelected = 0;
          this.answersSequence = new Array();

          for(var i = 0; i < this.answersArray.length; i++){
            if(this.answersArray[i].rightAnswer){
              this.answersSequence.push(i);
              answersSelected++;
            }
          }

          for(var i = 0; i < this.answersArray.length && answersSelected < this.maxAnswersAllowed; i++){
            if(!this.answersArray[i].rightAnswer){
              answersSelected++;
              this.answersSequence.push(i);
            }
          }
        } else {
        //  нет ограничений на количество ответов
          this.answersSequence = new Array();
          for(var i = 0; i < this.answersArray.length; i++){
            this.answersSequence.push(i);
          }
        }
      }
      trace("#FF00FF this.answersSequence == " + this.answersSequence);  
      var currentAnswerX = this.answersX.slice(0);
      var currentAnswerY = this.answersY.slice(0);
      
      //если элементы множеств раставлены по своим координатам (LAYOUT_NO)
      // запомним последовательность координат
     
      if (this.answersLayout == LAYOUT_NO && this.answersRandom){
        var originalX = [[],[]];
        var originalY = [[],[]];
        var counterForUnion = [0,0];
        for(var n = 0; n < originalSequence.length; n++){
          var theUnionNum = this.answersArray[originalSequence[n]].unionNum;
          if (theUnionNum == -1){
            trace("#FF0000 ОШИБКА: Внимательно проверьте правильность заполнения шаблонов")
            theUnionNum = 0
          }             var x = this.answersArray[originalSequence[n]].x;
          var y = this.answersArray[originalSequence[n]].y;
          originalX[theUnionNum].push(x);
          originalY[theUnionNum].push(y);
        }
      }
      //trace("#FF00FF originalX == " + originalX[0]); 
      for(var i = 0; i < this.answersSequence.length; i++){
        this.answersArray[this.answersSequence[i]].answerChecked = false;
          var theUnionNum = this.answersArray[this.answersSequence[i]].unionNum;
          if (theUnionNum == -1){
            trace("#FF0000 ОШИБКА: Внимательно проверьте правильность заполнения шаблонов")
            theUnionNum = 0
          }        
        
        switch(this.answersLayout){
        case LAYOUT_NO:
          this.destroyRelationLines();
          if(this.answersRandom){
            var cnt = counterForUnion[theUnionNum];
            this.answersArray[this.answersSequence[i]].x = originalX[theUnionNum][cnt];
            this.answersArray[this.answersSequence[i]].y = originalY[theUnionNum][cnt];
            counterForUnion[theUnionNum]++;
          } 
          this.answersArray[this.answersSequence[i]].showObject();
          break;
        case LAYOUT_VERTICAL:
          this.answersArray[this.answersSequence[i]].x = parseInt(currentAnswerX[theUnionNum]);
          this.answersArray[this.answersSequence[i]].y = parseInt(currentAnswerY[theUnionNum]);
          this.destroyRelationLines();
          this.answersArray[this.answersSequence[i]].showObject();
          var theSize = parseInt(currentAnswerY[theUnionNum]) + this.answersArray[this.answersSequence[i]].height;
          theSize += 20;                              // !!!!!!!!!!!!!!!
          currentAnswerY[theUnionNum] = theSize;
          break;
        case LAYOUT_HORIZONTAL:
          this.answersArray[this.answersSequence[i]].x = parseInt(currentAnswerX[theUnionNum]);
          this.answersArray[this.answersSequence[i]].y = parseInt(currentAnswerY[theUnionNum]);
          this.destroyRelationLines();
          this.answersArray[this.answersSequence[i]].showObject();
          currentAnswerX[theUnionNum] = parseInt(currentAnswerX[theUnionNum]) + this.answersArray[this.answersSequence[i]].width;
          currentAnswerX[theUnionNum] = currentAnswerX[theUnionNum] +  20;      // !!!!!!!!!!!!!!!
          break;
        }
        
        for(var j = 0; j < this.childObjects.length; j++){
          if(this.childObjects[j].type == "rnmc_stdCheckBox"){
            if(this.childObjects[j].autoAttachTarget == this.answersArray[this.answersSequence[i]].id){
              this.childObjects[j].uncheckObject();
            }
          }
        }
      }
    } else if(this.objectState == QUESTION_STATE_ANSWERED && this.excludeStyle == QUESTION_DISABLE){
      //  если на этот вопрос нельзя отвечать повторно и он уже отвечался
      //  восстанавливаем состояние этого вопроса которое было во время последнего ответа
      if(this.lastAnswersSequence){
        var currentAnswerX = this.answersX.slice(0);
        var currentAnswerY = this.answersY.slice(0);

        for(var i = 0; i < this.lastAnswersSequence.length; i++){
          var theUnionNum = this.answersArray[this.answersSequence[i]].unionNum;
          if (theUnionNum == -1){
            trace("#FF0000 ОШИБКА: Внимательно проверьте правильность заполнения шаблонов")
            theUnionNum = 0
          }    
          switch(this.answersLayout){
          case LAYOUT_NO:
            this.answersArray[this.lastAnswersSequence[i]].showObject();
            this.showRelationLines();
          case LAYOUT_VERTICAL:
            this.answersArray[this.answersSequence[i]].x = parseInt(currentAnswerX[theUnionNum]);
            this.answersArray[this.answersSequence[i]].y = parseInt(currentAnswerY[theUnionNum]);
            this.answersArray[this.lastAnswersSequence[i]].showObject();
            this.showRelationLines();
            var theSize = parseInt(currentAnswerY[theUnionNum]) + this.answersArray[this.answersSequence[i]].height;
            theSize += 20;                              // !!!!!!!!!!!!!!!
            currentAnswerY[theUnionNum] = theSize;                          // !!!!!!!!!!!!!!!
            break;
          case LAYOUT_HORIZONTAL:
            this.answersArray[this.answersSequence[i]].x = parseInt(currentAnswerX[theUnionNum]);
            this.answersArray[this.answersSequence[i]].y = parseInt(currentAnswerY[theUnionNum]);
            this.answersArray[this.answersSequence[i]].showObject();
            this.showRelationLines();
            currentAnswerX[theUnionNum] = parseInt(currentAnswerX[theUnionNum]) + this.answersArray[this.answersSequence[i]].width;
            currentAnswerX[theUnionNum] = currentAnswerX[theUnionNum] +  20;      // !!!!!!!!!!!!!!!
            break;
          }
          for(var j = 0; j < this.childObjects.length; j++){
            if(this.childObjects[j].type == "rnmc_stdCheckBox"){
              if(this.childObjects[j].autoAttachTarget == this.answersArray[this.lastAnswersSequence[i]].id){
                if(this.lastCheckedSequence[i] == 1){
                  this.childObjects[j].checkObject();
                } else {
                  this.childObjects[j].uncheckObject();
                }
                this.childObjects[j].disableObject();
              }
            }
          }
        }
      }  
    }
    
  //  корректное управление видимостью чекбоксов (потому как сами они не
  //  в состоянии понять, нжно показывацца или нет)
    for(var i = 0; i < this.answersArray.length; i++){
      if(this.answersSequence.indexOf(i) >= 0){
        //  значит этот вопрос показываем
        for(var j = 0; j < this.childObjects.length; j++){
          if(this.childObjects[j].type == "rnmc_stdCheckBox" &&
            this.childObjects[j].autoAttachTarget &&
            this.answersArray[i].id == this.childObjects[j].autoAttachTarget){
            this.childObjects[j].showObject(); 
          }
        }
      } else {
        for(var j = 0; j < this.childObjects.length; j++){
          if(this.childObjects[j].type == "rnmc_stdCheckBox" &&
            this.childObjects[j].autoAttachTarget &&
            this.answersArray[i].id == this.childObjects[j].autoAttachTarget){
            this.childObjects[j].hideObject(); 
          }
        }
      }
    }    
    
    
  //  отображаем содержимое вопроса после отображения ответов 
  //  для того чтобы работал автоаттач чекбоксов (пока без обновления расположения)
    for(var i = 0; i < this.childObjects.length; i++){
      if(this.childObjects[i].type != "unit" && this.childObjects[i].type != "rnmc_stdCheckBox"){
        if(this.childObjects[i].visibility == OBJECT_VISIBILITY_TRUE){
          this.childObjects[i].showObject();
        } 
      }
    }
    rnmc_stdMediaObject_showObject();
  }

//  прячем вопрос
  function hideObject(){
    for(var i = 0; i <  this.childObjects.length; i++){
      this.childObjects[i].hideObject();
    }  
    this.hideRelationLines();
    rnmc_stdMediaObject_hideObject();
  }
  
// Проверка выбранного отношения сразу после того, как
// ученик выберет два предполагаемых объекта.
// Если отношение соответствует истине, то связь
// обозначается линией соответствующего цвета, если нет -
// соединительная линия не обозначается. 
// Для любых двух объектов можно определить действия (action)
  function checkImmediately(){  
    // существующее количество правильных связей пока определяем по первому множеству
    var rightRelations = this.rightUnionsUnitsRelationsArr[0];   
    var rightSelected = 0;
    var wrongSelected = 0;
    // число попыток
    this.attemptsCount++
    for(var i = 0; i < this.relationsAray.length; i++){
      var res = this.relationsAray[i].checkRelation();
      if (res == true){
        if (this.rightRelationActions != null){
          for(var n = 0; n < this.rightRelationActions.length; n++){
            parent.dispatchAction(this.rightRelationActions[n]);
          }
        }      
        rightSelected++;
        this.lastRelation = true;
      } else if (res == -1){
        //  найдено не правильное отношение
        if (this.wrongRelationActions != null){
          for(var n = 0; n < this.wrongRelationActions.length; n++){
            parent.dispatchAction(this.wrongRelationActions[n]);
          }
        } 
          this.lastRelation = false;
          this.currentErrors++;
          wrongSelected++;
      } 
    }
    
    // если количество правильно выбранных отношений соответствует 
    // количеству установленных правильных отношений
    if (rightSelected == rightRelations){
      this.checkImmediatelyComplete = true;
    }
      
  }

// если режим проверки соответствует инструкции QUESTION_CHECK_AFTER
// (проверить отношения после того, как ученик установит предполагаемые связи),
// вызов данной функции следует после нажатия на кнопку "Проверить"
  function checkAnswers(){
    this.objectState = QUESTION_STATE_ANSWERED;

    var totalAnswers = this.relationsCount;
    var rightSelected = 0;
    var wrongSelected = 0;
    // существующее количество правильных связей пока определяем по первому множеству
    var rightRelations = this.rightUnionsUnitsRelationsArr[0]; 
    
    for(var i = 0; i < this.relationsAray.length; i++){
      if (this.relationsAray[i].checkRelation() == true){
        rightSelected++;
      } else {
          this.currentErrors++;
      }
    }
    this.attemptsCount = this.currentErrors;
    
    // подготовка данных для проверки результата
    var results;
    results = new scene.Utils.resultParam();
    results.init();
    results.allElements = this.relationsCount;
    results.allRightElements = this.rightUnionsUnitsRelationsArr[0];
    results.allWrongElements = this.relationsCount - this.rightUnionsUnitsRelationsArr[0];
    results.rightElements = rightSelected;
    results.wrongElements = this.currentErrors;
    results.attemptsCount = this.attemptsCount;
    results.isTimeout = this.isOnTimeout;
    results.countResult(this.crAlgorithm);
    this.currentResult = results.objectResult;
    

    parent.notifyQuestionAnswered(this.currentResult);
    if(!this.allowMultipleAttempts && this.excludeStyle == QUESTION_DISABLE){
    //  если нельзя отвечать повторно
      this.questionDisabled = true;
    //  сохраняем порядок отображения ответов
      this.lastAnswersSequence = this.answersSequence.slice(0);
    //  сохраняем расставленые галочки (в той последовательности,
    //  как выводились на экран - this.answersSequence)
    //  0 - галочки не стояло
    //  1 - галочка стояла
      if(this.lastCheckedSequence)
        this.lastCheckedSequence = null;
      this.lastCheckedSequence = new Array();
      
      for(var i = 0; i < this.answersSequence.length; i++){
        if(this.answersArray[this.answersSequence[i]].answerChecked){
          this.lastCheckedSequence.push(1);
        } else {
          this.lastCheckedSequence.push(0);
        }
      }
    }
    // *** если определен режим showCorrectRelations(показывать правильные отношения и this.checkMode == QUESTION_CHECK_AFTER)
    // найти все не отмеченные правильные отношения и отобразить
    // перебрать все парные точки, проверить выбраны ли они пользователем и соединить линией соответствующего цвета, если отношение не выбрано
    if (this.checkMode == QUESTION_CHECK_AFTER ){ 
      if (this.showCorrectRelationsAttempts == true){ 
        for(var i = 0; i <  this.childObjects.length; i++){
          if(this.childObjects[i].type == "unit"){
            if (this.childObjects[i].unionNum == 0){
            // определен свободный элемент из первого множества, следует перебрать все свободные элементы из второго
            // для нахождения правильной пары
              var firstObj = this.childObjects[i];
              //var firstObjId = firstObj.id;
              //var firstObjTargetsId = firstObj.targetsId;
              for(var j = 0; j <  this.childObjects.length; j++){
                  if(this.childObjects[j].type == "unit"){
                  if (this.childObjects[j].unionNum == 1){
                    // так как цедей у объекта может быть несколько проверим каждую
                    if (firstObj.targetsId != null){
                      if (firstObj.targetsId.length > 0){
                        for(var t=0; t<firstObj.targetsId.length; t++){
                          if (this.childObjects[j].id == firstObj.targetsId[t]){
                            var firstObjTargetId = firstObj.targetsId[t];
                            var secondObj = this.childObjects[j];
                            // проверить сущесвует ли подобная связь и если нет - создать
                            this.checkAndCreateCoorectLink(firstObj, secondObj, firstObjTargetId);
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      
      }
      //  выполнение действий при ответе с некоторым результатом
      if(this.currentResult == 100 && this.resultRightActions){
        for(var i = 0; i < this.resultRightActions.length; i++){
          parent.dispatchAction(this.resultRightActions[i]);
        }
      }
      if(this.currentResult == 0 && this.resultWrongActions){
        for(var i = 0; i < this.resultWrongActions.length; i++){
          parent.dispatchAction(this.resultWrongActions[i]);
        }
      }
      if(this.answeredBelowResultActions){
        for(var i = 0; i < this.answeredBelowResultActions.length; i++){
          if(parseInt(this.answeredBelowResultActions[i].eventParam) > this.currentResult)
            parent.dispatchAction(this.answeredBelowResultActions[i]);
        }
      }
      if(this.answeredAboveResultActions){
        for(var i = 0; i < this.answeredAboveResultActions.length; i++){
          if(parseInt(this.answeredBelowResultActions[i].eventParam) < this.currentResult)
            parent.dispatchAction(this.answeredAboveResultActions[i]);
        }
      }
      if(this.answeredAboveResultActions){
        for(var i = 0; i < this.answeredBetweenResultsActions.length; i++){
          var resultBounds = (this.answeredBetweenResultsActions[i].eventParam).split(";");
          if(resultBounds.length == 2){
            if(parseInt(resultBounds[0]) < this.currentResult && parseInt(resultBounds[1]) > this.currentResult)
              parent.dispatchAction(this.answeredBetweenResultsActions[i]);
          }
        }
      }
      // выполнение действий после выбора всех отношений
      if (this.resultCompleteActions != null){
        for(var t = 0; t < this.resultCompleteActions.length; t++){
          parent.dispatchAction(this.resultCompleteActions[t]);
        }
      }

    }

    // заблокировать активность checkBox 
      for(var i = 0; i <  this.childObjects.length; i++){
          this.childObjects[i].disableObject();
      }
      for(var l = 0; l <  this.relationsAray.length; l++){
        this.relationsAray[l].disableLine();
      }


  }
  // данное действие определено с параметром
  // в котором указана пара объектов, составляющих отношение
  function doRelationActions(firstId, secondId){ 
  trace("#00FFFF ***** function doRelationActions *****");
          // реализация события для выбранной связи
    var oneVar = firstId + "," + secondId;
    var twoVar = secondId + "," + firstId;
    if(this.relationActions){
      for(var i = 0; i < this.relationActions.length; i++){
      //trace("#00FF00 this.relationActions[i].eventParam == " + this.relationActions[i].eventParam);
        if(this.relationActions[i].eventParam){
          if (this.relationActions[i].eventParam == oneVar 
          || this.relationActions[i].eventParam == twoVar ){
            parent.dispatchAction(this.relationActions[i]);
          }
        }
      }
    }
  }
  
  // данная функция "срабатывает" после того, как ученик 
  // выведет курсор из зоны последненго выбранного объекта
  // используется, как правило, для освобождения сцены от 
  // действий, вызванных событиями, назначенными паре объектов (одиночной связи)
  function finishOperation(){
    
    if (this.checkMode == QUESTION_CHECK_IMMEDIATELY && this.lastRelation == false){ 
    // если последнее соединение неверное, удалить его
      this.lastRelation = null;
      var lastLineId = relationsAray.length - 1;
      this.relationsAray[lastLineId].hideLine();
      this.relationsAray[lastLineId].parent = null;
      this.relationsAray[lastLineId] = null;
      this.relationsAray.pop();
    }
    if (this.finishOperationActions != null){
      for(var t = 0; t < this.finishOperationActions.length; t++){
        parent.dispatchAction(this.finishOperationActions[t]);
      }
    }
    if (this.checkImmediatelyComplete == true){
      this.checkImmediatelyComplete = false;
      // заблокировать активность checkBox 
      for(var i = 0; i <  this.childObjects.length; i++){
        if(this.childObjects[i].type == "rnmc_stdCheckBox"){
          this.childObjects[i].disableObject();
        }
      }
      // выполнение действий после выбора всех отношений
      if (this.resultCompleteActions != null){
        for(var t = 0; t < this.resultCompleteActions.length; t++){
          parent.dispatchAction(this.resultCompleteActions[t]);
        }
      }
    }
  }
  
  function checkAndCreateCoorectLink(firstObj, secondObj, firstObjTargetId){
    // проверяем существует ли подобная связь
    var res = 0;
    if (this.relationsAray.length > 0){
      for(var r=0; r<this.relationsAray.length; r++){
        res = this.relationsAray[r].checkDuplicate(firstObj.id, firstObj.unionName, secondObj.id, secondObj.unionName);
        if(res == 1){
          break;
        }
      }
    }
    // если учащийся не выбрал правильные отношения следует дорисовать их
    // создаем исправленную линию 
    if( res == 0 ){
      var newObject = new Composition();
      newObject._class = "relationLine";
      newObject.parent = this;
      //newObject.parent = scene;
      newObject.visible = true;
      newObject.relationStatus = "correct";
      newObject.relationLineNormalColor = this.relationLineNormalColor;
      newObject.relationLineMarkColor = this.relationLineMarkColor;
      newObject.relationLineDisabledColor = this.relationLineDisabledColor;
      newObject.relationLineCorrectColor = this.relationLineCorrectColor;
      var firstObjX = firstObj.checkBox.x + Math.round(firstObj.checkBox.width/2);
      var firstObjY = firstObj.checkBox.y + Math.round(firstObj.checkBox.height/2);
      var secondObjX = secondObj.checkBox.x + Math.round(secondObj.checkBox.width/2);
      var secondObjY = secondObj.checkBox.y + Math.round(secondObj.checkBox.height/2);
      newObject.prepareFirstDot(firstObjX, firstObjY, firstObj.id, firstObj.targetsId, firstObj.unionName);
      newObject.relationObjId = relationsAray.length;
      this.relationsAray.push(newObject);
      newObject.showLine(secondObjX, secondObjY, secondObj.id, firstObj.id, secondObj.unionName);
    }
  }
  
  function deleteFromArray(theIndex){
    var theNewArray = new Array();
    for(var i = 0; i <  this.relationsAray.length; i++){
      if (i != theIndex){
        theNewArray.push(this.relationsAray[i]);
      }
    }
    this.relationsAray = theNewArray;
  }

  function resetAnswers(){
    //if(this.allowMultipleAttempts ){
      for(var i = 0; i <  this.childObjects.length; i++){
        if(this.childObjects[i].type == "rnmc_stdCheckBox"){
          this.childObjects[i].uncheckObject();
        } else if(this.childObjects[i].type == "unit"){
          this.childObjects[i].answerChecked = false;
        }
      }
    //}
  }
  
  function destroyRelationLines(){
    for(var i = 0; i <  this.relationsAray.length; i++){
      this.relationsAray[i].hideLine();
      this.relationsAray[i].parent = null;
      this.relationsAray[i] = null;
    }
    this.relationsAray = [];
  }  
  
  function showRelationLines(){
    var objCount = this.relationsAray.length;
    if (objCount > 0){
      for(var i = 0; i <  this.relationsAray.length; i++){
        this.relationsAray[i].showLine();
      }
    }
  }
  
  function hideRelationLines(){
  
    for(var i = 0; i <  this.relationsAray.length; i++){
      this.relationsAray[i].hideLine();
    }
  }

  function notifyAnswerChanged(answerId, newState, unionName){
    for(var i = 0; i <  this.childObjects.length; i++){
      if(this.childObjects[i].type == "rnmc_stdCheckBox"){
        if(this.childObjects[i].id != ("chkBox_" + answerId)){
          this.childObjects[i].uncheckObject();
        } else {
          this.childObjects[i].checkObject();
        }
      } else if(this.childObjects[i].type == "unit"){
        if(this.childObjects[i].id != answerId){
          this.childObjects[i].answerChecked = false;
        }
      }
    }
  }
  // ==========================================================================
  
  function cancelRelation(id){
    var relationsCount = this.relationsAray.length
    if (relationsCount > 0 ){
      if (this.relationsAray[relationsCount - 1].relationStatus == "open"){
        this.relationsAray[relationsCount - 1].parent = null;
        this.relationsAray[relationsCount - 1] = null;
        this.relationsAray.pop();
        this.currentUnionName = null;
      }
    }
  }
  
  function prepareRelation(checkBoxX, checkBoxY, id, targetsId, unionName){
    if (this.unionsCount > 0){
        // подготовить relationObj
        var relationObjId = this.checkRelationObj(checkBoxX, checkBoxY, id, targetsId, unionName);
        if (relationObjId >= 0){
          this.createRelation(relationObjId, checkBoxX, checkBoxY, id, targetsId, unionName);
          return 1;
        } else if (relationObjId == -1) {
          return -1;
        }  else if (relationObjId == undefined) {
          return -1;
        }
    }
  }
  
  function checkRelationObj(checkBoxX, checkBoxY, id, targetsId, unionName){
    var relationsCount = this.relationsAray.length;
    if(relationsCount > 0 && this.relationsAray[relationsCount - 1].relationStatus == "open"){
      var relationObj = this.relationsAray[relationsCount - 1];
      if (relationObj.firstDotUnionName != unionName){
        // проверяем существует ли подобная связь
        var res = 0;
        for(var i=0; i<relationsCount; i++){
          res = this.relationsAray[i].checkDuplicate(relationObj.firstDotId, relationObj.firstDotUnionName, id, unionName);
          if(res == 1){
            break;
          }
        }
        if(res == 0){
          return (relationsCount - 1);
        } else {
          //return undefined;
          // меняем свойства первой точки
          relationObj.prepareFirstDot(checkBoxX, checkBoxY, id, targetsId, unionName);
          return (-1);
        }
      } else {
        if (relationObj.firstDotId != id){
          // меняем свойства первой точки
          relationObj.prepareFirstDot(checkBoxX, checkBoxY, id, targetsId, unionName);
          return (-1);
        } else {
          // мы кликнули по той же точке, которая уже выделена и открыта
          return undefined;
        }
      }
    } else {
      var newObject = new Composition();
      newObject._class = "relationLine";
      newObject.parent = this;
      //newObject.parent = scene;
      newObject.visible = true;
      newObject.relationStatus = "open";
      newObject.relationLineNormalColor = this.relationLineNormalColor;
      newObject.relationLineMarkColor = this.relationLineMarkColor;
      newObject.relationLineDisabledColor = this.relationLineDisabledColor;
      newObject.relationLineCorrectColor = this.relationLineCorrectColor;
      newObject.prepareFirstDot(checkBoxX, checkBoxY, id, targetsId, unionName);
      newObject.relationObjId = relationsAray.length;
      this.relationsAray.push(newObject);
      return (-1);
    }
  }
  
  function createRelation(relationObjId, checkBoxX, checkBoxY, id, targetsId, unionName){
    var relationObj = this.relationsAray[relationObjId];
    relationObj.relationStatus = "close";
    relationObj.showLine(checkBoxX, checkBoxY, id, targetsId, unionName);
    if (this.relationsAray.length == 1 ){
      if (this.checkMode == QUESTION_CHECK_AFTER){
        parent.btnCheckAnswers.showObject();
      }
    }
    if (this.relationsAray.length >= this.relationsCount){
      this.resetAnswers();
      for(var j = 0; j < this.childObjects.length; j++){
        if(this.childObjects[j].type == "rnmc_stdCheckBox"){
          this.childObjects[j].disableObject();
        }
      }

    }
    
  }
  
  // подсчет максимального числа возможных связей
  function incrementRelCounter(theNumPos){
    if(this.unionsUnitsCountArray[theNumPos] > 0){
      this.unionsUnitsCountArray[theNumPos] ++;
    } else {
      this.unionsUnitsCountArray[theNumPos] = 1
    }
      
    // если речь идет о двух множествах, то максимальное количество связей будет
    if (this.unionsCount == 2){
      if(this.unionsUnitsCountArray[0] > 0 && this.unionsUnitsCountArray[1] > 0){
        this.relationsCount = this.unionsUnitsCountArray[0] * this.unionsUnitsCountArray[1];
      }
    }

  }
  
  function getResult(){
    if (this.checkMode != QUESTION_CHECK_AFTER ){  
    trace("#FF00FF getResult *********************");
      var rightRelations = this.rightUnionsUnitsRelationsArr[0];   
      var rightSelected = 0;

      for(var i = 0; i < this.relationsAray.length; i++){
        if (this.relationsAray[i].checkRelation() == true)
          rightSelected++;
      }

      // подготовка данных для проверки результата
      var results;
      results = new scene.Utils.resultParam();
      results.init();
      results.allElements = this.relationsCount;
      results.allRightElements = this.rightUnionsUnitsRelationsArr[0];
      results.allWrongElements = this.relationsCount - this.rightUnionsUnitsRelationsArr[0];
      results.rightElements = rightSelected;
      results.wrongElements = this.currentErrors;
      results.attemptsCount = this.attemptsCount;
      results.isTimeout = this.isOnTimeout;
      results.countResult(this.crAlgorithm);
      this.currentResult = results.objectResult;
    }    
    return this.currentResult;
  }
  
]]></script>
</composition>

<composition name="union_singleAnswer" class="rnmc_stdMediaGroup">
<script><![CDATA[
  this.type = "unit";
// 
  this.id = null;
//  номер множества в списке массива имен множеств (0 - перевый элемент массива)
  this.unionNum = 0;
//  правильность ответа
//  this.rightAnswer = false;
//  отмечен ли ответ (выбран) 
  this.answerChecked = false;
// 
  this.id = null;
//  список (массив) целей
  this.targetsId = null;
//  количество целей;
  this.targetsCount = 0;
//  имя множества
  this.unionName = null;
//последний активный чекбокс
  this.crntChkBoxId = null;
  
  function disableObject(){
  
  }
  
  function initFromNode(srcNode){
    var xmlNode = null;
    var xmlAttributeMap = null;
    var xmlAttribute = null;

    this.childObjects = new Array();
    this.loadChildsObject(srcNode);

    xmlAttributeMap = srcNode.attributes;
    if (xmlAttributeMap){
      xmlAttribute = xmlAttributeMap.getNamedItem("id");
      if (xmlAttribute != null && xmlAttribute.specified){
        this.id = xmlAttribute.value;
      }
    }

    xmlNode = srcNode.firstChild;
    while(xmlNode){
      if(xmlNode.nodeName == "param"){
        xmlAttributeMap = xmlNode.attributes;
        if (xmlAttributeMap){
          xmlAttribute = xmlAttributeMap.getNamedItem("x");
          if (xmlAttribute != null && xmlAttribute.specified){
            this.x = parseInt(xmlAttribute.value);
          }
          xmlAttribute = xmlAttributeMap.getNamedItem("y");
          if (xmlAttribute != null && xmlAttribute.specified){
            this.y = parseInt(xmlAttribute.value);
          }
          xmlAttribute = xmlAttributeMap.getNamedItem("targetsId");
          if (xmlAttribute != null && xmlAttribute.specified){
            this.targetsId = (xmlAttribute.value).split(",");
            this.targetsCount = this.targetsId.length;
          }
          xmlAttribute = xmlAttributeMap.getNamedItem("unionName");
          if (xmlAttribute != null && xmlAttribute.specified){
            this.unionName = xmlAttribute.value;
          }          
        }
      }
      xmlNode = xmlNode.nextSibling;
    }
  // если удачно  инициализированно
    return true;
  }

// показ ответа
  function showObject(){
  //  отображаем содержимое вопроса
    for(var i = 0; i < this.childObjects.length; i++){
      this.childObjects[i].showObject();
    }
    this.visible = true;
    // 20.01.2008 
    //this.onPress = onPressHandlerAlias;
  }

  function hideObject(){
    for(var i = 0; i < this.childObjects.length; i++){
      this.childObjects[i].hideObject();
    }
    
    //rnmc_stdMediaGroup_hideObject();
    this.visible = false;
  }

  function unloadObject(srcNode){
    if (this.checkBox)
      delete this.checkBox;
    rnmc_stdMediaGroup_unloadObject(srcNode);
  }

  function onPressHandler(){
    rnmc_stdMediaObject_onPressHandler();
    //if (this.checkBox)
    //  this.checkBox.pressButton();
  }

//  Никита: ПОКА ПЕРЕОПРЕДЕЛИЛ ТАК
//  лучшего способа пока не придумал
  function getPosition(){
    var positionArray = new Array();
    var realX = this.x;
    var realY = this.y;
    var realWidth = this.width;
    var realHeight = this.height;
    positionArray.push(realX, realY, realWidth, realHeight);
    return positionArray;
  }

  function onCheckBoxChanged(chkBoxId, currentSelected){
    var result = 0;
    if(currentSelected == CHECKBOX_STATE_CHECKED){
      this.crntChkBoxId = chkBoxId;
      this.answerChecked = true;
      var checkBoxX = this.checkBox.x + Math.round(this.checkBox.width/2);
      var checkBoxY = this.checkBox.y + Math.round(this.checkBox.height/2);
      var result = parent.prepareRelation(checkBoxX, checkBoxY, this.id, this.targetsId, this.unionName);
    } else {
      this.answerChecked = false;
      var result = parent.cancelRelation(this.id);
    }
    if (result == 1){
      //parent.resetAnswers();  
      if(parent.checkMode == QUESTION_CHECK_IMMEDIATELY){
        // проверить выбранное отношение
        parent.checkImmediately();
      }
      parent.resetAnswers();  
    } else if (result == -1){
      parent.notifyAnswerChanged(this.id, this.answerChecked);
    }
  }
  // функция срабатывает в момент выхода курсора из зоны "чекбокса"
  function onRollOutCheckBox(chkBoxId, currentSelected){
    if (currentSelected == 0 && this.crntChkBoxId == chkBoxId){
      parent.finishOperation();
    }
  }
  
]]></script>
</composition>

<composition name="relationLine">
<script><![CDATA[
  this.type = "relationLine";
// варианты расцветки связующей линии
  this.relationLineNormalColor = null;
  this.relationLineMarkColor = null;
  this.relationLineDisabledColor = null;
  this.relationLineCorrectColor = null;
  this.relationLineCurrentColor = null;
  this.firstDotId = null;
  this.firstDotX = null;
  this.firstDotY = null;
  this.firstDotTargetsId = null;
  this.firstDotUnionName = null;
  this.secondDotId = null;
  this.secondDotX = null;
  this.secondDotY = null;
  this.secondDotTargetsId = null;
  this.secondDotUnionName = null;  
  //----------------------------------------
  this.relationObjId = null;
  //----------------------------------------
  //   
  this.relationStatus = "open";
  // для каждой связи (правильной и не правильной) может быть установлено
  // определенное событие, если событие обработано
  // значение releaseDispatchAction следует заменить на true
  this.releaseDispatchAction = false;
      
  function prepareFirstDot(checkBoxX, checkBoxY, id, targetsId, unionName){
    this.firstDotId = id;
    this.firstDotX = checkBoxX;
    this.firstDotY = checkBoxY;
    this.firstDotTargetsId = targetsId;
    this.firstDotUnionName = unionName;
  }
  
  function checkDuplicate(theFirstDotId, theFirstDotUnionName, theSecondDotId, theSecondDotUnionName){
  var res = 0;
  if (this.firstDotId == theFirstDotId && this.firstDotUnionName ==  theFirstDotUnionName &&  this.secondDotId == theSecondDotId && this.secondDotUnionName == theSecondDotUnionName || this.secondDotId == theFirstDotId && this.secondDotUnionName ==  theFirstDotUnionName &&  this.firstDotId == theSecondDotId && this.firstDotUnionName == theSecondDotUnionName  ){
    res = 1;
    //trace("#FF0000 Подобное отношение уже существует");
  }
  
    return res;
  }
  
  function showLine(checkBoxX, checkBoxY, id, targetsId, unionName){
    if (id != undefined)
      this.secondDotId = id;
    if (checkBoxX != undefined)  
      this.secondDotX = checkBoxX;
    if (checkBoxY != undefined)    
      this.secondDotY = checkBoxY;
    if (targetsId != undefined)    
      this.secondDotTargetsId = targetsId;
    if (unionName != undefined)    
      this.secondDotUnionName = unionName;  
    // строим линию
    
    if (Player.version){// Играет во второй версии
      this.lineShape =  new Shape();
      this.lineShape.shapeArea = "{(" + this.firstDotX + "," + this.firstDotY + "),(" + this.secondDotX + "," + this.secondDotY + ")}";
      this.lineShape.opacity = 0.9;// Пока нету сглаживания, ставим вот так.
      
      if (this.relationLineCurrentColor != null){
        this.lineShape.color = this.relationLineCurrentColor;
      } else {
        if (this.relationStatus == "correct") {
          this.lineShape.color = this.relationLineCorrectColor;
        } else {
          this.lineShape.color = this.relationLineNormalColor;
        }
      }
      
      this.lineShape.weight = "3 px";
      
      this.lineShape.parent = this;  
      if (parent.checkMode == QUESTION_CHECK_AFTER ){
        this.lineShape.onPress = this.onPressHandlerAlias;
      }
    } else {
      this.lineShape =  new Composition();
      this.lineShape._class = "rnmc_stdLine";
      this.lineShape.visible = false;
      this.lineShape.parent = this;
      if (parent.checkMode == QUESTION_CHECK_AFTER ){
        this.lineShape.onPress = this.onPressHandlerAlias;
      }
      if (this.relationLineCurrentColor != null){
        this.lineShape.color = this.relationLineCurrentColor;
      } else {
        if (this.relationStatus == "correct") {
          this.lineShape.color = this.relationLineCorrectColor;
        } else {
          this.lineShape.color = this.relationLineNormalColor;
        }
      }
      
      this.lineShape.weight = 3;
      
      this.lineShape.draw_line(this.firstDotX,this.firstDotY,this.secondDotX,this.secondDotY);
      this.lineShape.visible = true;
    }
    
  }
  
  function onPressHandlerAlias()
  {
    pressHandler();
  }
  
  function pressHandler(){
      this.hideLine();
      //this.relationStatus = "open";
      parent.deleteFromArray(this.relationObjId);
      
  }
  
  // меняем цвет связующей лнии
  function changeColor(isTrue){
    if(isTrue == true){
      this.lineShape.color = this.colorT;
    } else {
      this.lineShape.color = this.colorE;
    }
  }

  function disableLine(){  
    if (this.lineShape != null){
      if (parent.checkMode == QUESTION_CHECK_AFTER ){
        this.lineShape.onPress = null;
      }
    }
  }

  function hideLine(){
    if (this.lineShape != null) {  
    this.lineShape.parent = null;
    this.lineShape = null;
    }
  }
  // проверка отношений 
  function checkRelation(){
    if (this.lineShape != null){
      // варианты: "fistDot" || "secondDot" || "not" || "bothDot"
      var targetsContainerIs = "not";
      if (this.firstDotTargetsId != null && this.secondDotTargetsId == null){
        targetsContainerIs = "fistDot";
      } else if (this.firstDotTargetsId == null && this.secondDotTargetsId != null) {
        targetsContainerIs = "secondDot";
      } else if (this.firstDotTargetsId != null && this.secondDotTargetsId != null) {
        targetsContainerIs = "bothDot";
      }
      
      if (this.releaseDispatchAction == false){
        this.releaseDispatchAction = true;
        parent.doRelationActions(this.firstDotId, this.secondDotId);
      }
      var thePos = -1;
      switch(targetsContainerIs){
      case "fistDot":
        thePos = scene.Utils.getOne(this.secondDotId, this.firstDotTargetsId);
        break;
      case "secondDot":
        thePos = scene.Utils.getOne(this.firstDotId, this.secondDotTargetsId);
        break;
      case "not":
        break;
      case "bothDot":
        thePos = (scene.Utils.getOne(this.firstDotId, this.secondDotTargetsId) || scene.Utils.getOne(this.secondDotId, this.firstDotTargetsId));
        break;        
      }
      if (thePos == -1){
        if (parent.parent.checkMode == QUESTION_CHECK_AFTER){
          this.relationLineCurrentColor = this.relationLineDisabledColor;
          this.lineShape.color = this.relationLineCurrentColor;
          if (!Player.version)
            this.lineShape.updateColor();
        } else if (parent.parent.checkMode == QUESTION_CHECK_IMMEDIATELY){
          this.lineShape.color = this.relationLineDisabledColor;
          if (!Player.version)
            this.lineShape.updateColor();        
        }
        return -1;
        
      } else {
        this.relationLineCurrentColor = this.relationLineMarkColor;
        this.lineShape.color = this.relationLineCurrentColor;
        
        if (!Player.version)
          this.lineShape.updateColor();
          
        return true;
      }
    } else {
      if (this.relationStatus == "open")
      return false;
    }
  }
  
  
]]></script>
</composition>
</rmml>
