コード例 #1
0
    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());
    }
コード例 #2
0
 /**
  * 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;
 }
コード例 #3
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();
    }
コード例 #4
0
    /**
     * @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']));
    }
コード例 #5
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());
    }
コード例 #6
0
 /**
  * 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);
     }
 }
コード例 #7
0
    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());
    }
コード例 #8
0
    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());
    }
コード例 #9
0
 /**
  * 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);
     }
 }
コード例 #10
0
 /**
  * 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);
 }
コード例 #11
0
    public function testCreateFromVariableDeclarationExtended()
    {
        $factory = $this->getMarshallerFactory('2.1.0');
        $element = $this->createDOMElement('
			<outcomeDeclaration xmlns="http://www.imsglobal.org/xsd/imsqti_v2p0" 
								identifier="outcome1" 
								baseType="pair" 
								cardinality="ordered"
								views="author candidate"
								normalMinimum="1.0"
								normalMaximum="2.1"
								masteryValue="1.5">
				<defaultValue>
					<value>A B</value>
					<value>B C</value>
				</defaultValue>
				<matchTable>
					<matchTableEntry sourceValue="0" targetValue="E F"/>
					<matchTableEntry sourceValue="1" targetValue="G H"/>
				</matchTable>
			</outcomeDeclaration>
		');
        $outcomeDeclaration = $factory->createMarshaller($element)->unmarshall($element);
        $outcomeVariable = OutcomeVariable::createFromDataModel($outcomeDeclaration);
        $this->assertEquals(Cardinality::ORDERED, $outcomeVariable->getCardinality());
        $defaultValue = $outcomeVariable->getDefaultValue();
        $this->assertEquals($outcomeVariable->getCardinality(), $defaultValue->getCardinality());
        $this->assertEquals($outcomeVariable->getBaseType(), $defaultValue->getBaseType());
        $this->assertEquals(1.0, $outcomeVariable->getNormalMinimum());
        $this->assertEquals(2.1, $outcomeVariable->getNormalMaximum());
        $this->assertEquals(1.5, $outcomeVariable->getMasteryValue());
        $matchTable = $outcomeVariable->getLookupTable();
        $this->assertInstanceOf('qtism\\data\\state\\MatchTable', $matchTable);
        $matchTableEntries = $matchTable->getMatchTableEntries();
        $this->assertEquals(2, count($matchTableEntries));
        $this->assertEquals(0, $matchTableEntries[0]->getSourceValue());
        $targetValue = $matchTableEntries[0]->getTargetValue();
        $this->assertTrue($targetValue->equals(new QtiPair('E', 'F')));
    }
コード例 #12
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);
 }
コード例 #13
0
    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();
    }
コード例 #14
0
 /**
  * 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);
 }
コード例 #15
0
 /**
  * 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);
     }
 }
コード例 #16
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);
     }
 }