public function testDefaultValueOnOutcomeSimple()
    {
        $rule = $this->createComponentFromXml('
			<setDefaultValue identifier="SCORE">
				<null/>
			</setDefaultValue>
		');
        $processor = new SetDefaultValueProcessor($rule);
        $response = new OutcomeVariable('SCORE', Cardinality::SINGLE, BaseType::FLOAT);
        $response->setDefaultValue(new Float(0.0));
        $state = new State(array($response));
        $processor->setState($state);
        $processor->process();
        $this->assertSame(null, $state->getVariable('SCORE')->getDefaultValue());
    }
 /**
  * Fill the variable $variableName with a correctly transformed $clientSideValue.
  *
  * @param string $variableName The variable identifier you want to fill.
  * @param array $clientSideValue The value received from the client-side representing the value of the variable with identifier $variableName.
  * @return Variable A Variable object filled with a correctly transformed $clientSideValue.
  * @throws OutOfBoundsException If no variable with $variableName is described in the item.
  * @throws OutOfRangeException If the $clientSideValue does not fit the target variable's baseType.
  */
 public function fill($variableName, $clientSideValue)
 {
     $variableDeclaration = $this->findVariableDeclaration($variableName);
     if ($variableDeclaration === false) {
         $itemId = $this->getItemRef()->getIdentifier();
         $msg = "Variable declaration with identifier '{$variableName}' not found in item '{$itemId}'.";
         throw new OutOfBoundsException($msg);
     }
     // Create Runtime Variable from Data Model.
     $runtimeVar = $variableDeclaration instanceof ResponseDeclaration ? ResponseVariable::createFromDataModel($variableDeclaration) : OutcomeVariable::createFromDataModel($variableDeclaration);
     // Set the data into the runtime variable thanks to the PCI JSON Unmarshaller
     // from QTISM.
     try {
         $unmarshaller = new PciJsonUnmarshaller(taoQtiCommon_helpers_Utils::getFileDatatypeManager());
         $value = $unmarshaller->unmarshall($clientSideValue);
         // Dev's note:
         // The PCI JSON Representation format does make the difference between multiple and ordered containers.
         // We then have to juggle a bit if the target variable has ordered cardinality.
         if ($value !== null && $value->getCardinality() === Cardinality::MULTIPLE && $variableDeclaration->getCardinality() === Cardinality::ORDERED) {
             $value = new OrderedContainer($value->getBaseType(), $value->getArrayCopy());
         }
         $runtimeVar->setValue($value);
     } catch (PciJsonUnmarshallingException $e) {
         $strClientSideValue = mb_substr(var_export($clientSideValue, true), 0, 50, TAO_DEFAULT_ENCODING);
         $msg = "Unable to put value '{$strClientSideValue}' into variable '{$variableName}'.";
         throw new OutOfRangeException($msg, 0, $e);
     }
     return $runtimeVar;
 }
    public function testResponseProcessingMatchCorrect()
    {
        $responseProcessing = $this->createComponentFromXml('
			<responseProcessing template="http://www.imsglobal.org/question/qti_v2p1/rptemplates/match_correct"/>
		');
        $responseDeclaration = $this->createComponentFromXml('
			<responseDeclaration identifier="RESPONSE" cardinality="single" baseType="identifier">
				<correctResponse>
					<value>ChoiceA</value>
				</correctResponse>
			</responseDeclaration>		
		');
        $outcomeDeclaration = $this->createComponentFromXml('
			<outcomeDeclaration identifier="SCORE" cardinality="single" baseType="float">
				<defaultValue>
					<value>0</value>
				</defaultValue>
			</outcomeDeclaration>
		');
        $respVar = ResponseVariable::createFromDataModel($responseDeclaration);
        $outVar = OutcomeVariable::createFromDataModel($outcomeDeclaration);
        $context = new State(array($respVar, $outVar));
        $engine = new ResponseProcessingEngine($responseProcessing, $context);
        // --> answer as a correct response.
        $context['RESPONSE'] = new Identifier('ChoiceA');
        $engine->process();
        $this->assertInstanceOf('qtism\\common\\datatypes\\Float', $context['SCORE']);
        $this->assertEquals(1.0, $context['SCORE']->getValue());
    }
Example #4
0
    public function testException()
    {
        $variableDeclaration = $this->createComponentFromXml('
			<outcomeDeclaration identifier="outcome1" baseType="integer" cardinality="single"/>
		');
        $variable = OutcomeVariable::createFromDataModel($variableDeclaration);
        $expr = $this->createComponentFromXml('<correct identifier="outcome1"/>');
        $processor = new CorrectProcessor($expr);
        $processor->setState(new State(array($variable)));
        $this->setExpectedException("qtism\\runtime\\expressions\\ExpressionProcessingException");
        $result = $processor->process();
    }
    /**
     * @dataProvider responseConditionMatchCorrectProvider
     * 
     * @param string $response A QTI Identifier
     * @param float $expectedScore The expected score for a given $response
     */
    public function testResponseConditionMatchCorrect($response, $expectedScore)
    {
        $rule = $this->createComponentFromXml('
			<responseCondition>
				<responseIf>
					<match>
						<variable identifier="RESPONSE"/>
						<correct identifier="RESPONSE"/>
					</match>
					<setOutcomeValue identifier="SCORE">
						<baseValue baseType="float">1</baseValue>
						</setOutcomeValue>
				</responseIf>
				<responseElse>
					<setOutcomeValue identifier="SCORE">
						<baseValue baseType="float">0</baseValue>
					</setOutcomeValue>
				</responseElse>
			</responseCondition>
		');
        $responseVarDeclaration = $this->createComponentFromXml('
			<responseDeclaration identifier="RESPONSE" cardinality="single" baseType="identifier">
				<correctResponse>
					<value>ChoiceA</value>
				</correctResponse>
			</responseDeclaration>
		');
        $responseVar = ResponseVariable::createFromDataModel($responseVarDeclaration);
        $this->assertTrue($responseVar->getCorrectResponse()->equals(new Identifier('ChoiceA')));
        // Set 'ChoiceA' to 'RESPONSE' in order to get a score of 1.0.
        $responseVar->setValue($response);
        $outcomeVarDeclaration = $this->createComponentFromXml('
			<outcomeDeclaration identifier="SCORE" cardinality="single" baseType="float">
				<defaultValue>
					<value>0</value>
				</defaultValue>
			</outcomeDeclaration>		
		');
        $outcomeVar = OutcomeVariable::createFromDataModel($outcomeVarDeclaration);
        $this->assertEquals(0, $outcomeVar->getDefaultValue()->getValue());
        $state = new State(array($responseVar, $outcomeVar));
        $processor = new ResponseConditionProcessor($rule);
        $processor->setState($state);
        $processor->process();
        $this->assertInstanceOf('qtism\\common\\datatypes\\Float', $state['SCORE']);
        $this->assertTrue($expectedScore->equals($state['SCORE']));
    }
Example #6
0
    public function testSingleCardinality()
    {
        $variableDeclaration = $this->createComponentFromXml('
			<outcomeDeclaration identifier="outcome1" baseType="boolean" cardinality="single">
				<defaultValue>
					<value>false</value>
				</defaultValue>
			</outcomeDeclaration>
		');
        $expr = $this->createComponentFromXml('<default identifier="outcome1"/>');
        $variable = OutcomeVariable::createFromDataModel($variableDeclaration);
        $processor = new DefaultProcessor($expr);
        $processor->setState(new State(array($variable)));
        $result = $processor->process();
        $this->assertInstanceOf('qtism\\common\\datatypes\\QtiBoolean', $result);
        $this->assertFalse($result->getValue());
    }
 /**
  * Fille the variable $variableName with a correctly transformed
  * $clientSideValue.
  * 
  * @param string $variableName The variable identifier you want to fill.
  * @param string $clientSideValue The value received from the client-side.
  * @return Variable A Variable object filled with a correctly transformed $clientSideValue.
  * @throws OutOfBoundsException If no variable with $variableName is described in the item.
  * @throws OutOfRangeException If the $clientSideValue does not fit the target variable's baseType.
  */
 public function fill($variableName, $clientSideValue)
 {
     $variable = null;
     $outcomeDeclarations = $this->getItemRef()->getOutcomeDeclarations();
     $responseDeclarations = $this->getItemRef()->getResponseDeclarations();
     if (isset($responseDeclarations[$variableName]) === true) {
         $variable = ResponseVariable::createFromDataModel($responseDeclarations[$variableName]);
     } else {
         if (isset($outcomeDeclarations[$variableName]) === true) {
             $variable = OutcomeVariable::createFromDataModel($outcomeDeclarations[$variableName]);
         }
     }
     if (empty($variable) === true) {
         $itemId = $this->getItemRef()->getIdentifier();
         $msg = "No variable declaration '{$variableName}' found in '{$itemId}'.";
         throw new OutOfBoundsException($msg);
     }
     common_Logger::d("Filling variable '" . $variable->getIdentifier() . "'.");
     if (is_array($clientSideValue) === false) {
         $clientSideValue = array($clientSideValue);
     }
     try {
         $finalValues = array();
         foreach ($clientSideValue as $val) {
             $finalValues[] = self::transform($variable->getBaseType(), $val);
         }
         if ($variable->getCardinality() === Cardinality::SINGLE) {
             $variable->setValue($finalValues[0]);
         } else {
             if ($variable->getCardinality() === Cardinality::MULTIPLE) {
                 $variable->setValue(new MultipleContainer($variable->getBaseType(), $finalValues));
             } else {
                 // Cardinality is ORDERED.
                 $variable->setValue(new OrderedContainer($variable->getBaseType(), $finalValues));
             }
         }
         return $variable;
     } catch (InvalidArgumentException $e) {
         if (is_array($clientSideValue)) {
             $clientSideValue = implode(',', $clientSideValue);
         }
         $msg = "An error occured while filling variable '{$variableName}' with client-side value '{$clientSideValue}':" . $e->getMessage();
         throw new InvalidArgumentException($msg, 0, $e);
     }
 }
    public function testLookupOutcomeValue()
    {
        $rule = $this->createComponentFromXml('
			<lookupOutcomeValue identifier="outcome1">
				<baseValue baseType="integer">2</baseValue>
			</lookupOutcomeValue>
		');
        $outcomeDeclaration = $this->createComponentFromXml('
			<outcomeDeclaration identifier="outcome1" cardinality="single" baseType="string">
				<matchTable>
					<matchTableEntry sourceValue="1" targetValue="String1!"/>
					<matchTableEntry sourceValue="2" targetValue="String2!"/>
				</matchTable>
			</outcomeDeclaration>
		');
        $outcomeVariable = OutcomeVariable::createFromDataModel($outcomeDeclaration);
        $context = new State(array($outcomeVariable));
        $engine = new RuleEngine($rule, $context);
        $this->assertSame(null, $context['outcome1']);
        $engine->process();
        $this->assertEquals('String2!', $context['outcome1']->getValue());
    }
    public function testLookupOutcomeValueSimpleInterpolationTable()
    {
        $rule = $this->createComponentFromXml('
			<lookupOutcomeValue identifier="outcome1">
				<baseValue baseType="float">2.0</baseValue>
			</lookupOutcomeValue>
		');
        $declaration = $this->createComponentFromXml('
			<outcomeDeclaration identifier="outcome1" cardinality="single" baseType="string">
				<interpolationTable defaultValue="What\'s going on?">
					<interpolationTableEntry sourceValue="1.0" includeBoundary="true" targetValue="Come get some!"/>
					<interpolationTableEntry sourceValue="2.0" includeBoundary="false" targetValue="Piece of cake!"/>
					<interpolationTableEntry sourceValue="3.0" includeBoundary="true" targetValue="Awesome!"/>
				</interpolationTable>
			</outcomeDeclaration>
		');
        $outcome = OutcomeVariable::createFromDataModel($declaration);
        $state = new State(array($outcome));
        $processor = new LookupOutcomeValueProcessor($rule);
        $processor->setState($state);
        $this->assertSame(null, $state['outcome1']);
        $processor->process();
        $this->assertInstanceOf('qtism\\common\\datatypes\\String', $state['outcome1']);
        $this->assertEquals('Awesome!', $state['outcome1']->getValue());
        // include the boundary for interpolationTableEntry[1]
        $table = $outcome->getLookupTable();
        $entries = $table->getInterpolationTableEntries();
        $entries[1]->setIncludeBoundary(true);
        $processor->process();
        $this->assertInstanceOf('qtism\\common\\datatypes\\String', $state['outcome1']);
        $this->assertEquals('Piece of cake!', $state['outcome1']->getValue());
        // get the default value.
        $expr = $rule->getExpression();
        $expr->setValue(4.0);
        $processor->process();
        $this->assertInstanceOf('qtism\\common\\datatypes\\String', $state['outcome1']);
        $this->assertEquals("What's going on?", $state['outcome1']->getValue());
    }
 /**
  * Create a new AssessmentTestSession object.
  *
  * @param AssessmentTest $assessmentTest The AssessmentTest object which represents the assessmenTest the context belongs to.
  * @param AbstractSessionManager $sessionManager The manager to be used to create new AssessmentItemSession objects.
  * @param Route $route The sequence of items that has to be taken for the session.
  */
 public function __construct(AssessmentTest $assessmentTest, AbstractSessionManager $sessionManager, Route $route)
 {
     parent::__construct();
     $this->setAssessmentTest($assessmentTest);
     $this->setSessionManager($sessionManager);
     $this->setRoute($route);
     $this->setAssessmentItemSessionStore(new AssessmentItemSessionStore());
     $this->setLastOccurenceUpdate(new SplObjectStorage());
     $this->setPendingResponseStore(new PendingResponseStore());
     $durationStore = new DurationStore();
     $this->setDurationStore($durationStore);
     // Take the outcomeDeclaration objects of the global scope.
     // Instantiate them with their defaults.
     foreach ($this->getAssessmentTest()->getOutcomeDeclarations() as $globalOutcome) {
         $variable = OutcomeVariable::createFromDataModel($globalOutcome);
         $variable->applyDefaultValue();
         $this->setVariable($variable);
     }
     $this->setSessionId('no_session_id');
     $this->setState(AssessmentTestSessionState::INITIAL);
 }
Example #11
0
 public function testClone()
 {
     $var = new OutcomeVariable('var', Cardinality::SINGLE, BaseType::INTEGER, new QtiInteger(25));
     $var->setDefaultValue(new QtiInteger(1));
     // value and default value must be independant.
     $clone = clone $var;
     $this->assertNotSame($var->getValue(), $clone->getValue());
     $this->assertNotSame($var->getDefaultValue(), $clone->getDefaultValue());
 }
 public function writeVariableValueProvider()
 {
     $rw_value = QtiBinaryStreamAccess::RW_VALUE;
     $rw_defaultValue = QtiBinaryStreamAccess::RW_DEFAULTVALUE;
     $rw_correctResponse = QtiBinaryStreamAccess::RW_CORRECTRESPONSE;
     $data = array();
     // -- Integers
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::INTEGER, new QtiInteger(26)));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::INTEGER, new QtiInteger(-34455)));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::INTEGER));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::INTEGER));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::INTEGER));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::INTEGER, new MultipleContainer(BaseType::INTEGER, array(new QtiInteger(-2147483647)))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::INTEGER, new OrderedContainer(BaseType::INTEGER, array(new QtiInteger(2147483647)))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::INTEGER, new MultipleContainer(BaseType::INTEGER, array(new QtiInteger(0), new QtiInteger(-1), new QtiInteger(1), new QtiInteger(-200000), new QtiInteger(200000)))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::INTEGER, new OrderedContainer(BaseType::INTEGER, array(new QtiInteger(0), new QtiInteger(-1), new QtiInteger(1), new QtiInteger(-200000), new QtiInteger(200000)))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::INTEGER, new MultipleContainer(BaseType::INTEGER, array(null))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::INTEGER, new OrderedContainer(BaseType::INTEGER, array(null))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::INTEGER, new MultipleContainer(BaseType::INTEGER, array(new QtiInteger(0), null, new QtiInteger(1), null, new QtiInteger(200000)))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::INTEGER, new OrderedContainer(BaseType::INTEGER, array(new QtiInteger(0), null, new QtiInteger(1), null, new QtiInteger(200000)))));
     $v = new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::INTEGER);
     $v->setDefaultValue(null);
     $data[] = array($v, $rw_defaultValue);
     $v = new ResponseVariable('VAR', Cardinality::SINGLE, BaseType::INTEGER);
     $v->setDefaultValue(new QtiInteger(26));
     $data[] = array($v, $rw_defaultValue);
     $v = new ResponseVariable('VAR', Cardinality::SINGLE, BaseType::INTEGER);
     $v->setCorrectResponse(new QtiInteger(26));
     $data[] = array($v, $rw_correctResponse);
     $v = new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::INTEGER);
     $v->setDefaultValue(new QtiInteger(-34455));
     $data[] = array($v, $rw_defaultValue);
     $v = new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::INTEGER);
     $v->setDefaultValue(new MultipleContainer(BaseType::INTEGER, array(new QtiInteger(-2147483647))));
     $data[] = array($v, $rw_defaultValue);
     $v = new ResponseVariable('VAR', Cardinality::ORDERED, BaseType::INTEGER);
     $v->setCorrectResponse(new OrderedContainer(BaseType::INTEGER, array(new QtiInteger(2147483647))));
     $data[] = array($v, $rw_correctResponse);
     // -- Floats
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::FLOAT, new QtiFloat(26.1)));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::FLOAT, new QtiFloat(-34455.0)));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::FLOAT));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::FLOAT));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::FLOAT));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::FLOAT, new MultipleContainer(BaseType::FLOAT, array(new QtiFloat(-21474.654)))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::FLOAT, new OrderedContainer(BaseType::FLOAT, array(new QtiFloat(21474.3)))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::FLOAT, new MultipleContainer(BaseType::FLOAT, array(new QtiFloat(0.0), new QtiFloat(-1.1), new QtiFloat(1.1), new QtiFloat(-200000.005), new QtiFloat(200000.005)))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::FLOAT, new OrderedContainer(BaseType::FLOAT, array(new QtiFloat(0.0), new QtiFloat(-1.1), new QtiFloat(1.1), new QtiFloat(-200000.005), new QtiFloat(200000.005)))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::FLOAT, new MultipleContainer(BaseType::FLOAT, array(null))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::FLOAT, new OrderedContainer(BaseType::FLOAT, array(null))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::FLOAT, new MultipleContainer(BaseType::FLOAT, array(new QtiFloat(0.0), null, new QtiFloat(1.1), null, new QtiFloat(200000.005)))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::FLOAT, new OrderedContainer(BaseType::FLOAT, array(new QtiFloat(0.0), null, new QtiFloat(1.1), null, new QtiFloat(200000.005)))));
     $v = new ResponseVariable('VAR', Cardinality::SINGLE, BaseType::FLOAT);
     $v->setDefaultValue(new QtiFloat(26.1));
     $data[] = array($v, $rw_defaultValue);
     $v = new ResponseVariable('VAR', Cardinality::SINGLE, BaseType::FLOAT);
     $v->setCorrectResponse(new QtiFloat(26.1));
     $data[] = array($v, $rw_correctResponse);
     $v = new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::FLOAT);
     $v->setDefaultValue(new OrderedContainer(BaseType::FLOAT, array(new QtiFloat(0.0), new QtiFloat(-1.1), new QtiFloat(1.1), new QtiFloat(-200000.005), new QtiFloat(200000.005))));
     $data[] = array($v, $rw_defaultValue);
     $v = new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::FLOAT);
     $v->setDefaultValue(new MultipleContainer(BaseType::FLOAT, array(new QtiFloat(0.0), new QtiFloat(-1.1), new QtiFloat(1.1), new QtiFloat(-200000.005), new QtiFloat(200000.005))));
     $data[] = array($v, $rw_defaultValue);
     // $data[] = array();
     // -- Booleans
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::BOOLEAN, new QtiBoolean(true)));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::BOOLEAN, new QtiBoolean(false)));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::BOOLEAN));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::BOOLEAN));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::BOOLEAN));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::BOOLEAN, new MultipleContainer(BaseType::BOOLEAN, array(new QtiBoolean(true)))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::BOOLEAN, new OrderedContainer(BaseType::BOOLEAN, array(new QtiBoolean(false)))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::BOOLEAN, new MultipleContainer(BaseType::BOOLEAN, array(new QtiBoolean(false), new QtiBoolean(true), new QtiBoolean(false), new QtiBoolean(true), new QtiBoolean(true)))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::BOOLEAN, new OrderedContainer(BaseType::BOOLEAN, array(new QtiBoolean(false), new QtiBoolean(true), new QtiBoolean(false), new QtiBoolean(true), new QtiBoolean(false)))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::BOOLEAN, new MultipleContainer(BaseType::BOOLEAN, array(null))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::BOOLEAN, new OrderedContainer(BaseType::BOOLEAN, array(null))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::BOOLEAN, new MultipleContainer(BaseType::BOOLEAN, array(new QtiBoolean(false), null, new QtiBoolean(true), null, new QtiBoolean(false)))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::BOOLEAN, new OrderedContainer(BaseType::BOOLEAN, array(new QtiBoolean(false), null, new QtiBoolean(true), null, new QtiBoolean(false)))));
     $v = new ResponseVariable('VAR', Cardinality::SINGLE, BaseType::BOOLEAN);
     $v->setDefaultValue(new QtiBoolean(true));
     $data[] = array($v, $rw_defaultValue);
     $v = new ResponseVariable('VAR', Cardinality::SINGLE, BaseType::BOOLEAN);
     $v->setCorrectResponse(new QtiBoolean(true));
     $data[] = array($v, $rw_correctResponse);
     $v = new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::IDENTIFIER);
     $v->setDefaultValue(new MultipleContainer(BaseType::IDENTIFIER, array(new QtiIdentifier('identifier1'), new QtiIdentifier('identifier2'), new QtiIdentifier('identifier3'), new QtiIdentifier('identifier4'), new QtiIdentifier('identifier5'))));
     $data[] = array($v, $rw_defaultValue);
     // -- Identifiers
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::IDENTIFIER, new QtiIdentifier('identifier')));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::IDENTIFIER, new QtiIdentifier('non-identifier')));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::IDENTIFIER));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::IDENTIFIER));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::IDENTIFIER));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::IDENTIFIER, new MultipleContainer(BaseType::IDENTIFIER, array(new QtiIdentifier('identifier')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::IDENTIFIER, new OrderedContainer(BaseType::IDENTIFIER, array(new QtiIdentifier('identifier')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::IDENTIFIER, new MultipleContainer(BaseType::IDENTIFIER, array(new QtiIdentifier('identifier1'), new QtiIdentifier('identifier2'), new QtiIdentifier('identifier3'), new QtiIdentifier('identifier4'), new QtiIdentifier('identifier5')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::IDENTIFIER, new OrderedContainer(BaseType::IDENTIFIER, array(new QtiIdentifier('identifier1'), new QtiIdentifier('identifier2'), new QtiIdentifier('identifier3'), new QtiIdentifier('X-Y-Z'), new QtiIdentifier('identifier4')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::IDENTIFIER, new MultipleContainer(BaseType::IDENTIFIER, array(null))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::IDENTIFIER, new OrderedContainer(BaseType::IDENTIFIER, array(null))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::IDENTIFIER, new MultipleContainer(BaseType::IDENTIFIER, array(new QtiIdentifier('identifier1'), null, new QtiIdentifier('identifier2'), null, new QtiIdentifier('identifier3')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::IDENTIFIER, new OrderedContainer(BaseType::IDENTIFIER, array(new QtiIdentifier('identifier1'), null, new QtiIdentifier('identifier2'), null, new QtiIdentifier('identifier3')))));
     $v = new ResponseVariable('VAR', Cardinality::SINGLE, BaseType::IDENTIFIER);
     $v->setDefaultValue(new QtiIdentifier('non-identifier'));
     $data[] = array($v, $rw_defaultValue);
     $v = new ResponseVariable('VAR', Cardinality::SINGLE, BaseType::IDENTIFIER);
     $v->setDefaultValue(new QtiIdentifier('non-identifier'));
     $data[] = array($v, $rw_correctResponse);
     // -- URIs
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::URI, new QtiUri('http://www.my.uri')));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::URI, new QtiUri('http://www.my.uri')));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::URI));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::URI));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::URI));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::URI, new MultipleContainer(BaseType::URI, array(new QtiUri('http://www.my.uri')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::URI, new OrderedContainer(BaseType::URI, array(new QtiUri('http://www.my.uri')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::URI, new MultipleContainer(BaseType::URI, array(new QtiUri('http://www.my.uri1'), new QtiUri('http://www.my.uri2'), new QtiUri('http://www.my.uri3'), new QtiUri('http://www.my.uri4'), new QtiUri('http://www.my.uri6')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::URI, new OrderedContainer(BaseType::URI, array(new QtiUri('http://www.my.uri1'), new QtiUri('http://www.my.uri2'), new QtiUri('http://www.my.uri3'), new QtiUri('http://www.my.uri4'), new QtiUri('http://www.my.uri5')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::URI, new MultipleContainer(BaseType::URI, array(null))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::URI, new OrderedContainer(BaseType::URI, array(null))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::URI, new MultipleContainer(BaseType::URI, array(new QtiUri('http://www.my.uri1'), null, new QtiUri('http://www.my.uri2'), null, new QtiUri('http://www.my.uri3')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::URI, new OrderedContainer(BaseType::URI, array(new QtiUri('http://www.my.uri1'), null, new QtiUri('http://www.my.uri2'), null, new QtiUri('http://www.my.uri3')))));
     $v = new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::URI);
     $v->setDefaultValue(new QtiUri('http://www.my.uri'));
     $data[] = array($v, $rw_defaultValue);
     $v = new ResponseVariable('VAR', Cardinality::MULTIPLE, BaseType::URI);
     $v->setDefaultValue(new MultipleContainer(BaseType::URI, array(new QtiUri('http://www.my.uri1'), null, new QtiUri('http://www.my.uri2'), null, new QtiUri('http://www.my.uri3'))));
     $data[] = array($v, $rw_defaultValue);
     $v = new ResponseVariable('VAR', Cardinality::MULTIPLE, BaseType::URI);
     $v->setCorrectResponse(new MultipleContainer(BaseType::URI, array(new QtiUri('http://www.my.uri1'), null, new QtiUri('http://www.my.uri2'), null, new QtiUri('http://www.my.uri3'))));
     $data[] = array($v, $rw_correctResponse);
     // -- Durations
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::DURATION, new QtiDuration('P3DT2H1S')));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::DURATION));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::DURATION));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::DURATION));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::DURATION, new MultipleContainer(BaseType::DURATION, array(new QtiDuration('PT2S')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::DURATION, new OrderedContainer(BaseType::DURATION, array(new QtiDuration('P2YT2S')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::DURATION, new MultipleContainer(BaseType::DURATION, array(new QtiDuration('PT1S'), new QtiDuration('PT2S'), new QtiDuration('PT3S'), new QtiDuration('PT4S'), new QtiDuration('PT5S')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::DURATION, new OrderedContainer(BaseType::DURATION, array(new QtiDuration('PT1S'), new QtiDuration('PT2S'), new QtiDuration('PT3S'), new QtiDuration('PT4S'), new QtiDuration('PT5S')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::DURATION, new MultipleContainer(BaseType::DURATION, array(null))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::DURATION, new OrderedContainer(BaseType::DURATION, array(null))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::DURATION, new MultipleContainer(BaseType::DURATION, array(new QtiDuration('P4D'), null, new QtiDuration('P10D'), null, new QtiDuration('P20D')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::DURATION, new OrderedContainer(BaseType::DURATION, array(new QtiDuration('P4D'), null, new QtiDuration('P10D'), null, new QtiDuration('P20D')))));
     $v = new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::DURATION);
     $v->setDefaultValue(new QtiDuration('P3DT2H1S'));
     $data[] = array($v, $rw_defaultValue);
     $v = new ResponseVariable('VAR', Cardinality::ORDERED, BaseType::DURATION);
     $v->setDefaultValue(new OrderedContainer(BaseType::DURATION, array(new QtiDuration('PT1S'), new QtiDuration('PT2S'), new QtiDuration('PT3S'), new QtiDuration('PT4S'), new QtiDuration('PT5S'))));
     array($v, $rw_defaultValue);
     $v = new ResponseVariable('VAR', Cardinality::ORDERED, BaseType::DURATION);
     $v->setCorrectResponse(new OrderedContainer(BaseType::DURATION, array(new QtiDuration('PT1S'), new QtiDuration('PT2S'), new QtiDuration('PT3S'), new QtiDuration('PT4S'), new QtiDuration('PT5S'))));
     array($v, $rw_correctResponse);
     // -- Pairs
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::PAIR, new QtiPair('A', 'B')));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::PAIR));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::PAIR));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::PAIR));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::PAIR, new MultipleContainer(BaseType::PAIR, array(new QtiPair('A', 'B')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::PAIR, new OrderedContainer(BaseType::PAIR, array(new QtiPair('A', 'B')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::PAIR, new MultipleContainer(BaseType::PAIR, array(new QtiPair('A', 'B'), new QtiPair('C', 'D'), new QtiPair('E', 'F'), new QtiPair('G', 'H'), new QtiPair('I', 'J')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::PAIR, new OrderedContainer(BaseType::PAIR, array(new QtiPair('A', 'B'), new QtiPair('C', 'D'), new QtiPair('E', 'F'), new QtiPair('G', 'H'), new QtiPair('I', 'J')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::PAIR, new MultipleContainer(BaseType::PAIR, array(null))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::PAIR, new OrderedContainer(BaseType::PAIR, array(null))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::PAIR, new MultipleContainer(BaseType::PAIR, array(new QtiPair('A', 'B'), null, new QtiPair('C', 'D'), null, new QtiPair('E', 'F')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::PAIR, new OrderedContainer(BaseType::PAIR, array(new QtiPair('A', 'B'), null, new QtiPair('D', 'E'), null, new QtiPair('F', 'G')))));
     $v = new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::PAIR);
     $v->setDefaultValue(new QtiPair('A', 'B'));
     $data[] = array($v, $rw_defaultValue);
     $v = new ResponseVariable('VAR', Cardinality::MULTIPLE, BaseType::PAIR);
     $v->setDefaultValue(new MultipleContainer(BaseType::PAIR, array(null)));
     $data[] = array($v, $rw_defaultValue);
     $v = new ResponseVariable('VAR', Cardinality::MULTIPLE, BaseType::PAIR);
     $v->setCorrectResponse(new MultipleContainer(BaseType::PAIR, array(null)));
     $data[] = array($v, $rw_correctResponse);
     // -- DirectedPairs
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::DIRECTED_PAIR, new QtiDirectedPair('A', 'B')));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::DIRECTED_PAIR));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::DIRECTED_PAIR));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::DIRECTED_PAIR));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::DIRECTED_PAIR, new MultipleContainer(BaseType::DIRECTED_PAIR, array(new QtiDirectedPair('A', 'B')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::DIRECTED_PAIR, new OrderedContainer(BaseType::DIRECTED_PAIR, array(new QtiDirectedPair('A', 'B')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::DIRECTED_PAIR, new MultipleContainer(BaseType::DIRECTED_PAIR, array(new QtiDirectedPair('A', 'B'), new QtiDirectedPair('C', 'D'), new QtiDirectedPair('E', 'F'), new QtiDirectedPair('G', 'H'), new QtiDirectedPair('I', 'J')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::DIRECTED_PAIR, new OrderedContainer(BaseType::DIRECTED_PAIR, array(new QtiDirectedPair('A', 'B'), new QtiDirectedPair('C', 'D'), new QtiDirectedPair('E', 'F'), new QtiDirectedPair('G', 'H'), new QtiDirectedPair('I', 'J')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::DIRECTED_PAIR, new MultipleContainer(BaseType::DIRECTED_PAIR, array(null))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::DIRECTED_PAIR, new OrderedContainer(BaseType::DIRECTED_PAIR, array(null))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::DIRECTED_PAIR, new MultipleContainer(BaseType::DIRECTED_PAIR, array(new QtiDirectedPair('A', 'B'), null, new QtiDirectedPair('C', 'D'), null, new QtiDirectedPair('E', 'F')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::DIRECTED_PAIR, new OrderedContainer(BaseType::DIRECTED_PAIR, array(new QtiDirectedPair('A', 'B'), null, new QtiDirectedPair('D', 'E'), null, new QtiDirectedPair('F', 'G')))));
     $v = new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::DIRECTED_PAIR);
     $v->setDefaultValue(new QtiDirectedPair('A', 'B'));
     array($v, $rw_defaultValue);
     $v = new ResponseVariable('VAR', Cardinality::MULTIPLE, BaseType::DIRECTED_PAIR);
     $v->setDefaultValue(new MultipleContainer(BaseType::DIRECTED_PAIR, array(new QtiDirectedPair('A', 'B'), new QtiDirectedPair('C', 'D'), new QtiDirectedPair('E', 'F'), new QtiDirectedPair('G', 'H'), new QtiDirectedPair('I', 'J'))));
     $data[] = array($v, $rw_defaultValue);
     $v = new ResponseVariable('VAR', Cardinality::MULTIPLE, BaseType::DIRECTED_PAIR);
     $v->setCorrectResponse(new MultipleContainer(BaseType::DIRECTED_PAIR, array(new QtiDirectedPair('A', 'B'), new QtiDirectedPair('C', 'D'), new QtiDirectedPair('E', 'F'), new QtiDirectedPair('G', 'H'), new QtiDirectedPair('I', 'J'))));
     $data[] = array($v, $rw_correctResponse);
     // -- Points
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::POINT, new QtiPoint(50, 50)));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::POINT));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::POINT));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::POINT));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::POINT, new MultipleContainer(BaseType::POINT, array(new QtiPoint(50, 50)))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::POINT, new OrderedContainer(BaseType::POINT, array(new QtiPoint(50, 50)))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::POINT, new MultipleContainer(BaseType::POINT, array(new QtiPoint(50, 50), new QtiPoint(0, 0), new QtiPoint(100, 50), new QtiPoint(150, 3), new QtiPoint(50, 50)))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::POINT, new OrderedContainer(BaseType::POINT, array(new QtiPoint(50, 50), new QtiPoint(0, 35), new QtiPoint(30, 50), new QtiPoint(40, 55), new QtiPoint(0, 0)))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::POINT, new MultipleContainer(BaseType::POINT, array(null))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::POINT, new OrderedContainer(BaseType::POINT, array(null))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::POINT, new MultipleContainer(BaseType::POINT, array(new QtiPoint(30, 50), null, new QtiPoint(20, 50), null, new QtiPoint(45, 32)))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::POINT, new OrderedContainer(BaseType::POINT, array(new QtiPoint(20, 11), null, new QtiPoint(36, 43), null, new QtiPoint(50, 44)))));
     $v = new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::POINT);
     $v->setDefaultValue(new QtiPoint(50, 50));
     $data[] = array($v, $rw_defaultValue);
     $v = new ResponseVariable('VAR', Cardinality::ORDERED, BaseType::POINT);
     $v->setDefaultValue(new OrderedContainer(BaseType::POINT, array(new QtiPoint(50, 50))));
     $data[] = array($v, $rw_defaultValue);
     $v = new ResponseVariable('VAR', Cardinality::ORDERED, BaseType::POINT);
     $v->setCorrectResponse(new OrderedContainer(BaseType::POINT, array(new QtiPoint(50, 50))));
     $data[] = array($v, $rw_correctResponse);
     // IntOrIdentifiers
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::INT_OR_IDENTIFIER, new QtiIntOrIdentifier(26)));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::INT_OR_IDENTIFIER, new QtiIntOrIdentifier('Q01')));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::INT_OR_IDENTIFIER));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::INT_OR_IDENTIFIER));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::INT_OR_IDENTIFIER));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::INT_OR_IDENTIFIER, new MultipleContainer(BaseType::INT_OR_IDENTIFIER, array(new QtiIntOrIdentifier(-2147483647)))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::INT_OR_IDENTIFIER, new OrderedContainer(BaseType::INT_OR_IDENTIFIER, array(new QtiIntOrIdentifier('Section1')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::INT_OR_IDENTIFIER, new MultipleContainer(BaseType::INT_OR_IDENTIFIER, array(new QtiIntOrIdentifier(0), new QtiIntOrIdentifier('Q01'), new QtiIntOrIdentifier('Q02'), new QtiIntOrIdentifier(-200000), new QtiIntOrIdentifier(200000)))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::INT_OR_IDENTIFIER, new OrderedContainer(BaseType::INT_OR_IDENTIFIER, array(new QtiIntOrIdentifier(0), new QtiIntOrIdentifier(-1), new QtiIntOrIdentifier(1), new QtiIntOrIdentifier(-200000), new QtiIntOrIdentifier('Q05')))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::INT_OR_IDENTIFIER, new MultipleContainer(BaseType::INT_OR_IDENTIFIER, array(null))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::INT_OR_IDENTIFIER, new OrderedContainer(BaseType::INT_OR_IDENTIFIER, array(null))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::INT_OR_IDENTIFIER, new MultipleContainer(BaseType::INT_OR_IDENTIFIER, array(new QtiIntOrIdentifier(0), null, new QtiIntOrIdentifier(1), null, new QtiIntOrIdentifier(200000)))));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::INT_OR_IDENTIFIER, new OrderedContainer(BaseType::INT_OR_IDENTIFIER, array(new QtiIntOrIdentifier(0), null, new QtiIntOrIdentifier('Q01'), null, new QtiIntOrIdentifier(200000)))));
     $v = new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::INT_OR_IDENTIFIER);
     $v->setDefaultValue(new QtiIntOrIdentifier(26));
     $data[] = array($v, $rw_defaultValue);
     $v = new OutcomeVariable('VAR', Cardinality::SINGLE, BaseType::INT_OR_IDENTIFIER);
     $v->setDefaultValue(new QtiIntOrIdentifier('Q01'));
     $data[] = array($v, $rw_defaultValue);
     $v = new OutcomeVariable('VAR', Cardinality::ORDERED, BaseType::INT_OR_IDENTIFIER);
     $v->setDefaultValue(new OrderedContainer(BaseType::INT_OR_IDENTIFIER, array(new QtiIntOrIdentifier(0), new QtiIntOrIdentifier(-1), new QtiIntOrIdentifier(1), new QtiIntOrIdentifier(-200000), new QtiIntOrIdentifier('Q05'))));
     $data[] = array($v, $rw_defaultValue);
     // Files
     $data[] = array(new ResponseVariable('VAR', Cardinality::SINGLE, BaseType::FILE, FileSystemFile::retrieveFile(self::samplesDir() . 'datatypes/file/text-plain_text_data.txt')));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::MULTIPLE, BaseType::FILE, new MultipleContainer(BaseType::FILE, array(FileSystemFile::retrieveFile(self::samplesDir() . 'datatypes/file/text-plain_text_data.txt'), FileSystemFile::retrieveFile(self::samplesDir() . 'datatypes/file/text-plain_noname.txt')))));
     $v = new ResponseVariable('VAR', Cardinality::SINGLE, BaseType::FILE);
     $v->setDefaultValue(FileSystemFile::retrieveFile(self::samplesDir() . 'datatypes/file/text-plain_text_data.txt'));
     $data[] = array($v, $rw_defaultValue);
     $v = new ResponseVariable('VAR', Cardinality::SINGLE, BaseType::FILE);
     $v->setDefaultValue(FileSystemFile::retrieveFile(self::samplesDir() . 'datatypes/file/text-plain_text_data.txt'));
     $data[] = array($v, $rw_correctResponse);
     // Records
     $data[] = array(new OutcomeVariable('VAR', Cardinality::RECORD));
     $data[] = array(new OutcomeVariable('VAR', Cardinality::RECORD, -1, new RecordContainer(array('key1' => null))));
     $data[] = array(new OutcomeVariable('Var', Cardinality::RECORD, -1, new RecordContainer(array('key1' => new QtiDuration('PT1S'), 'key2' => new QtiFloat(25.5), 'key3' => new QtiInteger(2), 'key4' => new QtiString('String!'), 'key5' => null, 'key6' => new QtiBoolean(true)))));
     $v = new OutcomeVariable('VAR', Cardinality::RECORD, -1);
     $v->setDefaultValue(new RecordContainer(array('key1' => null)));
     array($v, $rw_defaultValue);
     $v = new ResponseVariable('Var', Cardinality::RECORD, -1);
     $v->setDefaultValue(new RecordContainer(array('key1' => new QtiDuration('PT1S'), 'key2' => new QtiFloat(25.5), 'key3' => new QtiInteger(2), 'key4' => new QtiString('String!'), 'key5' => null, 'key6' => new QtiBoolean(true))));
     $data[] = array($v, $rw_defaultValue);
     $v = new ResponseVariable('Var', Cardinality::RECORD, -1);
     $v->setCorrectResponse(new RecordContainer(array('key1' => new QtiDuration('PT1S'), 'key2' => new QtiFloat(25.5), 'key3' => new QtiInteger(2), 'key4' => new QtiString('String!'), 'key5' => null, 'key6' => new QtiBoolean(true))));
     $data[] = array($v, $rw_defaultValue);
     return $data;
 }
Example #13
0
 /**
  * Create a new AssessmentItemSession object. 
  * 
  * * The built-in response variables 'numAttempts' and 'duration' will be created and set up with appropriate default values, respectively Integer(0) and Duration('PT0S').
  * * The built-in outcome variable 'completionStatus' will be created and set up with an appropriate default value of  String('not_attempted').
  * * The item session is set up with a default ItemSessionControl object. If you want a specific ItemSessionControl object to rule the session, use the setItemSessionControl() method.
  * * The item session is set up with no TimeLimits object. If you want to set a a specfici TimeLimits object to rule the session, use the setTimeLimits() method.
  *
  * @param \qtism\data\IAssessmentItem $assessmentItem The description of the item that the session handles.
  * @param integer $navigationMode (optional) A value from the NavigationMode enumeration.
  * @param integer $submissionMode (optional) A value from the SubmissionMode enumeration.
  * @throws \InvalidArgumentException If $navigationMode or $submission is not a value from the NavigationMode/SubmissionMode enumeration.
  * @see \qtism\runtime\tests\AssessmentItemSession::setItemSessionControl() The setItemSessionControl() method.
  * @see \qtism\runtime\tests\AssessmentItemSession::setTimeLimits() The setTimeLimits() method.
  */
 public function __construct(IAssessmentItem $assessmentItem, $navigationMode = NavigationMode::LINEAR, $submissionMode = SubmissionMode::INDIVIDUAL)
 {
     parent::__construct();
     $this->setAssessmentItem($assessmentItem);
     $this->setItemSessionControl(new ItemSessionControl());
     $this->setNavigationMode($navigationMode);
     $this->setSubmissionMode($submissionMode);
     // -- Create the built-in response variables.
     $this->setVariable(new ResponseVariable('numAttempts', Cardinality::SINGLE, BaseType::INTEGER, new QtiInteger(0)));
     $this->setVariable(new ResponseVariable('duration', Cardinality::SINGLE, BaseType::DURATION, new QtiDuration('PT0S')));
     // -- Create the built-in outcome variables.
     $this->setVariable(new OutcomeVariable('completionStatus', Cardinality::SINGLE, BaseType::IDENTIFIER, new QtiIdentifier(self::COMPLETION_STATUS_NOT_ATTEMPTED)));
     // -- Create item specific outcome, response and template variables.
     foreach ($assessmentItem->getOutcomeDeclarations() as $outcomeDeclaration) {
         $outcomeVariable = OutcomeVariable::createFromDataModel($outcomeDeclaration);
         $this->setVariable($outcomeVariable);
     }
     foreach ($this->getAssessmentItem()->getResponseDeclarations() as $responseDeclaration) {
         $responseVariable = ResponseVariable::createFromDataModel($responseDeclaration);
         $this->setVariable($responseVariable);
     }
     foreach ($assessmentItem->getTemplateDeclarations() as $templateDeclaration) {
         $templateVariable = TemplateVariable::createFromDataModel($templateDeclaration);
         $this->setVariable($templateVariable);
     }
     // -- Perform choice shuffling for interactions by creating the Shuffling States for this item session.
     $shufflingStates = new ShufflingCollection();
     foreach ($assessmentItem->getShufflings() as $shuffling) {
         $shufflingStates[] = $shuffling->shuffle();
     }
     $this->setShufflingStates($shufflingStates);
 }
<?php

use qtism\runtime\common\State;
use qtism\data\storage\xml\XmlDocument;
use qtism\runtime\rendering\markup\xhtml\XhtmlRenderingEngine;
use qtism\runtime\rendering\markup\AbstractMarkupRenderingEngine;
use qtism\runtime\common\OutcomeVariable;
use qtism\common\enums\BaseType;
use qtism\common\enums\Cardinality;
require_once dirname(__FILE__) . '/../../qtism/qtism.php';
$doc = new XmlDocument();
$doc->load('../samples/rendering/itemfeedback_1.xml');
$outcome1 = new OutcomeVariable('FEEDBACK', Cardinality::SINGLE, BaseType::IDENTIFIER, '');
$renderer = new XhtmlRenderingEngine();
if (isset($argv[1]) && $argv[1] === 'CONTEXT_AWARE') {
    $renderer->setFeedbackShowHidePolicy(AbstractMarkupRenderingEngine::CONTEXT_AWARE);
    if (isset($argv[2])) {
        $outcome1->setValue($argv[2]);
    }
}
$renderer->setState(new State(array($outcome1)));
$rendering = $renderer->render($doc->getDocumentComponent());
$rendering->formatOutput = true;
echo $rendering->saveXML();
<?php

use qtism\runtime\common\State;
use qtism\data\storage\xml\XmlDocument;
use qtism\runtime\rendering\markup\xhtml\XhtmlRenderingEngine;
use qtism\runtime\rendering\markup\AbstractMarkupRenderingEngine;
use qtism\runtime\common\OutcomeVariable;
use qtism\common\enums\BaseType;
use qtism\common\enums\Cardinality;
use qtism\common\datatypes\Identifier;
require_once dirname(__FILE__) . '/../../vendor/autoload.php';
$doc = new XmlDocument();
$doc->load(dirname(__FILE__) . '/../samples/rendering/itemfeedback_1.xml');
$outcome1 = new OutcomeVariable('FEEDBACK', Cardinality::SINGLE, BaseType::IDENTIFIER, new Identifier(''));
$renderer = new XhtmlRenderingEngine();
if (isset($argv[1]) && $argv[1] === 'CONTEXT_AWARE') {
    $renderer->setFeedbackShowHidePolicy(AbstractMarkupRenderingEngine::CONTEXT_AWARE);
    if (isset($argv[2])) {
        $outcome1->setValue(new Identifier($argv[2]));
    }
}
$renderer->setState(new State(array($outcome1)));
$rendering = $renderer->render($doc->getDocumentComponent());
$rendering->formatOutput = true;
echo $rendering->saveXML();
    public function testOutcomeDeclaration()
    {
        $this->setExpectedException("qtism\\runtime\\expressions\\ExpressionProcessingException");
        $variableDeclaration = $this->createComponentFromXml('
			<outcomeDeclaration identifier="response1" baseType="integer" cardinality="multiple">
				<mapping>
					<mapEntry mapKey="0" mappedValue="0.0"/>
				</mapping>
			</outcomeDeclaration>
		');
        $variable = OutcomeVariable::createFromDataModel($variableDeclaration);
        $mapResponseExpr = $this->createComponentFromXml('<mapResponse identifier="response1"/>');
        $mapResponseProcessor = new MapResponseProcessor($mapResponseExpr);
        $mapResponseProcessor->setState(new State(array($variable)));
        $mapResponseProcessor->process();
    }
 /**
  * Retrieve an AssessmentTestSession object from storage by $sessionId.
  *
  * @param \qtism\data\AssessmentTest $test
  * @param string $sessionId
  * @return \qtism\runtime\tests\AssessmentTestSession An AssessmentTestSession object.
  * @throws \qtism\runtime\storage\common\StorageException If the AssessmentTestSession could not be retrieved from storage.
  */
 public function retrieve(AssessmentTest $test, $sessionId)
 {
     try {
         $stream = $this->getRetrievalStream($sessionId);
         $stream->open();
         $access = $this->createBinaryStreamAccess($stream);
         // -- Deal with intrinsic values of the Test Session.
         $assessmentTestSessionState = $access->readTinyInt();
         $currentPosition = $access->readTinyInt();
         if ($access->readBoolean() === true) {
             $timeReference = $access->readDateTime();
         } else {
             $timeReference = null;
         }
         // Build the route and the item sessions.
         $route = new Route();
         $lastOccurenceUpdate = new SplObjectStorage();
         $itemSessionStore = new AssessmentItemSessionStore();
         $pendingResponseStore = new PendingResponseStore();
         $routeCount = $access->readTinyInt();
         // Create the item session factory that will be used to instantiate
         // new item sessions.
         for ($i = 0; $i < $routeCount; $i++) {
             $routeItem = $access->readRouteItem($this->getSeeker());
             $route->addRouteItemObject($routeItem);
             // An already instantiated session for this route item?
             if ($access->readBoolean() === true) {
                 $itemSession = $access->readAssessmentItemSession($this->getManager(), $this->getSeeker());
                 // last-update
                 if ($access->readBoolean() === true) {
                     $lastOccurenceUpdate[$routeItem->getAssessmentItemRef()] = $routeItem->getOccurence();
                 }
                 // pending-responses
                 if ($access->readBoolean() === true) {
                     $pendingResponseStore->addPendingResponses($access->readPendingResponses($this->getSeeker()));
                 }
                 $itemSessionStore->addAssessmentItemSession($itemSession, $routeItem->getOccurence());
             }
         }
         $route->setPosition($currentPosition);
         $manager = $this->getManager();
         $assessmentTestSession = $manager->createAssessmentTestSession($test, $route);
         $assessmentTestSession->setAssessmentItemSessionStore($itemSessionStore);
         $assessmentTestSession->setSessionId($sessionId);
         $assessmentTestSession->setState($assessmentTestSessionState);
         $assessmentTestSession->setLastOccurenceUpdate($lastOccurenceUpdate);
         $assessmentTestSession->setPendingResponseStore($pendingResponseStore);
         $assessmentTestSession->setTimeReference($timeReference);
         // Deal with test session configuration.
         // -- AutoForward (not in use anymore, consume it anyway).
         $access->readBoolean();
         // Build the test-level global scope, composed of Outcome Variables.
         foreach ($test->getOutcomeDeclarations() as $outcomeDeclaration) {
             $outcomeVariable = OutcomeVariable::createFromDataModel($outcomeDeclaration);
             $access->readVariableValue($outcomeVariable);
             $assessmentTestSession->setVariable($outcomeVariable);
         }
         // Build the duration store.
         $durationStore = new DurationStore();
         $durationCount = $access->readShort();
         for ($i = 0; $i < $durationCount; $i++) {
             $varName = $access->readString();
             $durationVariable = new OutcomeVariable($varName, Cardinality::SINGLE, BaseType::DURATION);
             $access->readVariableValue($durationVariable);
             $durationStore->setVariable($durationVariable);
         }
         $assessmentTestSession->setDurationStore($durationStore);
         $stream->close();
         return $assessmentTestSession;
     } catch (Exception $e) {
         $msg = "An error occured while retrieving AssessmentTestSession. " . $e->getMessage();
         throw new StorageException($msg, StorageException::RETRIEVAL, $e);
     }
 }
<?php

use qtism\runtime\rendering\markup\AbstractMarkupRenderingEngine;
use qtism\runtime\common\State;
use qtism\common\enums\BaseType;
use qtism\common\enums\Cardinality;
use qtism\common\datatypes\Identifier;
use qtism\runtime\common\OutcomeVariable;
use qtism\data\storage\xml\XmlDocument;
use qtism\runtime\rendering\markup\xhtml\XhtmlRenderingEngine;
require_once dirname(__FILE__) . '/../../vendor/autoload.php';
$doc = new XmlDocument();
$doc->load(dirname(__FILE__) . '/../samples/rendering/itembodywithfeedback_1.xml');
$outcome1 = new OutcomeVariable('outcome1', Cardinality::SINGLE, BaseType::IDENTIFIER, new Identifier(''));
$outcome2 = new OutcomeVariable('outcome2', Cardinality::SINGLE, BaseType::IDENTIFIER, new Identifier(''));
$renderer = new XhtmlRenderingEngine();
if (isset($argv[1]) && $argv[1] === 'CONTEXT_AWARE') {
    $renderer->setFeedbackShowHidePolicy(AbstractMarkupRenderingEngine::CONTEXT_AWARE);
    if (isset($argv[2])) {
        $outcome1->setValue(new Identifier($argv[2]));
    }
    if (isset($argv[3])) {
        $outcome2->setValue(new Identifier($argv[3]));
    }
}
$renderer->setState(new State(array($outcome1, $outcome2)));
$rendering = $renderer->render($doc->getDocumentComponent());
$rendering->formatOutput = true;
echo $rendering->saveXML();
 /**
  * Start the item session. The item session is started when the related item
  * becomes eligible for the candidate.
  * 
  * * ResponseVariable objects involved in the session will be set a value of NULL.
  * * OutcomeVariable objects involved in the session will be set their default value if any. Otherwise, they are set to NULL unless their baseType is integer or float. In this case, the value is 0 or 0.0.
  * * The state of the session is set to INITIAL.
  * 
  */
 public function beginItemSession()
 {
     // We initialize the item session and its variables.
     foreach ($this->getAssessmentItem()->getOutcomeDeclarations() as $outcomeDeclaration) {
         // Outcome variables are instantiantiated as part of the item session.
         // Their values may be initialized with a default value if they have one.
         $outcomeVariable = OutcomeVariable::createFromDataModel($outcomeDeclaration);
         $outcomeVariable->initialize();
         $outcomeVariable->applyDefaultValue();
         $this->setVariable($outcomeVariable);
     }
     foreach ($this->getAssessmentItem()->getResponseDeclarations() as $responseDeclaration) {
         // Response variables are instantiated as part of the item session.
         // Their values are always initialized to NULL.
         $responseVariable = ResponseVariable::createFromDataModel($responseDeclaration);
         $responseVariable->initialize();
         $this->setVariable($responseVariable);
     }
     // The session gets the INITIAL state, ready for a first attempt.
     $this->setState(AssessmentItemSessionState::INITIAL);
     $this['duration'] = new Duration('PT0S');
     $this['numAttempts']->setValue(0);
     $this['completionStatus']->setValue(self::COMPLETION_STATUS_NOT_ATTEMPTED);
 }
 public function testIsNull()
 {
     $outcome = new OutcomeVariable('var1', Cardinality::SINGLE, BaseType::STRING);
     $this->assertTrue($outcome->isNull());
     $outcome->setValue(new String(''));
     $this->assertTrue($outcome->isNull());
     $outcome->setValue(new String('String!'));
     $this->assertFalse($outcome->isNull());
     $outcome = new OutcomeVariable('var1', Cardinality::SINGLE, BaseType::INTEGER);
     $this->assertTrue($outcome->isNull());
     $outcome->setValue(new Integer(0));
     $this->assertFalse($outcome->isNull());
     $outcome->setValue(new Integer(-1));
     $this->assertFalse($outcome->isNull());
     $outcome->setValue(new Integer(100));
     $this->assertFalse($outcome->isNull());
     $outcome = new OutcomeVariable('var1', Cardinality::SINGLE, BaseType::FLOAT);
     $this->assertTrue($outcome->isNull());
     $outcome->setValue(new Float(0.25));
     $this->assertFalse($outcome->isNull());
     $outcome->setValue(new Float(-1.2));
     $this->assertFalse($outcome->isNull());
     $outcome->setValue(new Float(100.12));
     $this->assertFalse($outcome->isNull());
     $outcome = new OutcomeVariable('var1', Cardinality::SINGLE, BaseType::BOOLEAN);
     $this->assertTrue($outcome->isNull());
     $outcome->setValue(new Boolean(true));
     $this->assertFalse($outcome->isNull());
     $outcome->setValue(new Boolean(false));
     $this->assertFalse($outcome->isNull());
     $outcome = new OutcomeVariable('var1', Cardinality::MULTIPLE, BaseType::BOOLEAN);
     $this->assertTrue($outcome->isNull());
     $value = $outcome->getValue();
     $value[] = new Boolean(true);
     $this->assertFalse($outcome->isNull());
     $outcome = new OutcomeVariable('var1', Cardinality::ORDERED, BaseType::STRING);
     $this->assertTrue($outcome->isNull());
     $value = $outcome->getValue();
     $value[] = new String('string!');
     $this->assertFalse($outcome->isNull());
     $outcome = new OutcomeVariable('var1', Cardinality::RECORD);
     $this->assertTrue($outcome->isNull());
     $value = $outcome->getValue();
     $value['point1'] = new Point(100, 200);
     $this->assertFalse($outcome->isNull());
 }
 /**
  * Read an AssessmentItemSession from the current binary stream.
  * 
  * @param AbstractSessionManager $manager
  * @param AssessmentTestSeeker $seeker An AssessmentTestSeeker object from where 'assessmentItemRef', 'outcomeDeclaration' and 'responseDeclaration' QTI components will be pulled out.
  * @throws QtiBinaryStreamAccessException
  */
 public function readAssessmentItemSession(AbstractSessionManager $manager, AssessmentTestSeeker $seeker)
 {
     try {
         $itemRefPosition = $this->readShort();
         $assessmentItemRef = $seeker->seekComponent('assessmentItemRef', $itemRefPosition);
         $session = $manager->createAssessmentItemSession($assessmentItemRef);
         $session->setAssessmentItem($assessmentItemRef);
         $session->setState($this->readTinyInt());
         $session->setNavigationMode($this->readTinyInt());
         $session->setSubmissionMode($this->readTinyInt());
         // The is-attempting field was added in Binary Storage v2.
         if (QtiBinaryConstants::QTI_BINARY_STORAGE_VERSION >= 2) {
             $session->setAttempting($this->readBoolean());
         }
         if ($this->readBoolean() === true) {
             $itemSessionControl = $seeker->seekComponent('itemSessionControl', $this->readShort());
             $session->setItemSessionControl($itemSessionControl);
         }
         if ($session->getState() !== AssessmentItemSessionState::NOT_SELECTED) {
             $session['numAttempts'] = new Integer($this->readTinyInt());
             $session['duration'] = $this->readDuration();
             $session['completionStatus'] = new Identifier($this->readString());
             if ($session['numAttempts']->getValue() > 0) {
                 $session->setTimeReference($this->readDateTime());
             }
         }
         $varCount = $this->readTinyInt();
         for ($i = 0; $i < $varCount; $i++) {
             $isOutcome = $this->readBoolean();
             $varPosition = $this->readShort();
             $variable = null;
             try {
                 $variable = $seeker->seekComponent($isOutcome === true ? 'outcomeDeclaration' : 'responseDeclaration', $varPosition);
             } catch (OutOfBoundsException $e) {
                 $msg = "No variable found at position {$varPosition} in the assessmentTest tree structure.";
                 throw new QtiBinaryStreamAccessException($msg, $this, QtiBinaryStreamAccessException::ITEM_SESSION, $e);
             }
             $variable = $variable instanceof OutcomeDeclaration ? OutcomeVariable::createFromDataModel($variable) : ResponseVariable::createFromDataModel($variable);
             // If we are here, we have our variable.
             $this->readVariableValue($variable);
             $session->setVariable($variable);
         }
         return $session;
     } catch (BinaryStreamAccessException $e) {
         $msg = "An error occured while reading an assessment item session.";
         throw new QtiBinaryStreamAccessException($msg, $this, QtiBinaryStreamAccessException::ITEM_SESSION, $e);
     } catch (OutOfBoundsException $e) {
         $msg = "No assessmentItemRef found at position {$itemRefPosition} in the assessmentTest tree structure.";
         throw new QtiBinaryStreamAccessException($msg, $this, QtiBinaryStreamAccessException::ITEM_SESSION, $e);
     }
 }
<?php

use qtism\runtime\rendering\markup\AbstractMarkupRenderingEngine;
use qtism\runtime\common\State;
use qtism\common\enums\BaseType;
use qtism\common\enums\Cardinality;
use qtism\runtime\common\OutcomeVariable;
use qtism\data\storage\xml\XmlDocument;
use qtism\runtime\rendering\markup\xhtml\XhtmlRenderingEngine;
require_once dirname(__FILE__) . '/../../qtism/qtism.php';
$doc = new XmlDocument();
$doc->load('../samples/rendering/itembodywithfeedback_1.xml');
$outcome1 = new OutcomeVariable('outcome1', Cardinality::SINGLE, BaseType::IDENTIFIER, '');
$outcome2 = new OutcomeVariable('outcome2', Cardinality::SINGLE, BaseType::IDENTIFIER, '');
$renderer = new XhtmlRenderingEngine();
if (isset($argv[1]) && $argv[1] === 'CONTEXT_AWARE') {
    $renderer->setFeedbackShowHidePolicy(AbstractMarkupRenderingEngine::CONTEXT_AWARE);
    if (isset($argv[2])) {
        $outcome1->setValue($argv[2]);
    }
    if (isset($argv[3])) {
        $outcome2->setValue($argv[3]);
    }
}
$renderer->setState(new State(array($outcome1, $outcome2)));
$rendering = $renderer->render($doc->getDocumentComponent());
$rendering->formatOutput = true;
echo $rendering->saveXML();
Example #23
0
 /**
  * Write an AssessmetnItemSession from the current binary stream.
  *
  * @param \qtism\runtime\storage\common\AssessmentTestSeeker $seeker The AssessmentTestSeeker object from where the position of components will be pulled out.
  * @param \qtism\runtime\tests\AssessmentItemSession $session An AssessmentItemSession object.
  * @throws \qtism\runtime\storage\binary\QtiBinaryStreamAccessException
  */
 public function writeAssessmentItemSession(AssessmentTestSeeker $seeker, AssessmentItemSession $session)
 {
     try {
         $this->writeShort($seeker->seekPosition($session->getAssessmentItem()));
         $this->writeTinyInt($session->getState());
         $this->writeTinyInt($session->getNavigationMode());
         $this->writeTinyInt($session->getSubmissionMode());
         $this->writeBoolean($session->isAttempting());
         $isItemSessionControlDefault = $session->getItemSessionControl()->isDefault();
         if ($isItemSessionControlDefault === true) {
             $this->writeBoolean(false);
         } else {
             $this->writeBoolean(true);
             $this->writeShort($seeker->seekPosition($session->getItemSessionControl()));
         }
         $this->writeTinyInt($session['numAttempts']->getValue());
         $this->writeDuration($session['duration']);
         $this->writeString($session['completionStatus']->getValue());
         $timeReference = $session->getTimeReference();
         if (is_null($timeReference) === true) {
             // Describe that we have no time reference for the session.
             $this->writeBoolean(false);
         } else {
             // Describe that we have a time reference for the session.
             $this->writeBoolean(true);
             // Write the time reference.
             $this->writeDateTime($timeReference);
         }
         // Write the session variables.
         // (minus the 3 built-in variables)
         $varCount = count($session) - 3;
         $this->writeTinyInt($varCount);
         $itemOutcomes = $session->getAssessmentItem()->getOutcomeDeclarations();
         $itemResponses = $session->getAssessmentItem()->getResponseDeclarations();
         $itemTemplates = $session->getAssessmentItem()->getTemplateDeclarations();
         foreach ($session->getKeys() as $varId) {
             if (in_array($varId, array('numAttempts', 'duration', 'completionStatus')) === false) {
                 $var = $session->getVariable($varId);
                 if ($var instanceof OutcomeVariable) {
                     $variableDeclaration = $itemOutcomes[$varId];
                     $variable = OutcomeVariable::createFromDataModel($variableDeclaration);
                     $varNature = 0;
                 } elseif ($var instanceof ResponseVariable) {
                     $variableDeclaration = $itemResponses[$varId];
                     $variable = ResponseVariable::createFromDataModel($variableDeclaration);
                     $varNature = 1;
                 } elseif ($var instanceof TemplateVariable) {
                     $variableDeclaration = $itemTemplates[$varId];
                     $variable = TemplateVariable::createFromDataModel($variableDeclaration);
                     $varNature = 2;
                 }
                 try {
                     $this->writeShort($varNature);
                     $this->writeShort($seeker->seekPosition($variableDeclaration));
                     // If defaultValue or correct response is different from what's inside
                     // the variable declaration, just write it.
                     $hasDefaultValue = !Utils::equals($variable->getDefaultValue(), $var->getDefaultValue());
                     $hasCorrectResponse = false;
                     if ($varNature === 1 && !Utils::equals($variable->getCorrectResponse(), $var->getCorrectResponse())) {
                         $hasCorrectResponse = true;
                     }
                     $this->writeBoolean($hasDefaultValue);
                     $this->writeBoolean($hasCorrectResponse);
                     $this->writeVariableValue($var, self::RW_VALUE);
                     if ($hasDefaultValue === true) {
                         $this->writeVariableValue($var, self::RW_DEFAULTVALUE);
                     }
                     if ($hasCorrectResponse === true) {
                         $this->writeVariableValue($var, self::RW_CORRECTRESPONSE);
                     }
                 } catch (OutOfBoundsException $e) {
                     $msg = "No variable found in the assessmentTest tree structure.";
                     throw new QtiBinaryStreamAccessException($msg, $this, QtiBinaryStreamAccessException::ITEM_SESSION, $e);
                 }
             }
         }
         // Write shuffling states if any.
         $shufflingStates = $session->getShufflingStates();
         $this->writeTinyInt(count($shufflingStates));
         foreach ($shufflingStates as $shufflingState) {
             $this->writeShufflingState($shufflingState);
         }
     } catch (BinaryStreamAccessException $e) {
         $msg = "An error occured while writing an assessment item session.";
         throw new QtiBinaryStreamAccessException($msg, $this, QtiBinaryStreamAccessException::ITEM_SESSION, $e);
     } catch (OutOfBoundsException $e) {
         $msg = "No assessmentItemRef found in the assessmentTest tree structure.";
         throw new QtiBinaryStreamAccessException($msg, $this, QtiBinaryStreamAccessException::ITEM_SESSION, $e);
     }
 }