/**
  * Add an AssessmentItemSession to the store, for a given $occurence number.
  *
  * @param \qtism\runtime\tests\AssessmentItemSession $assessmentItemSession
  * @param integer $occurence The occurence number of the session.
  */
 public function addAssessmentItemSession(AssessmentItemSession $assessmentItemSession, $occurence = 0)
 {
     $assessmentItemRef = $assessmentItemSession->getAssessmentItem();
     if (isset($this->shelves[$assessmentItemRef]) === false) {
         $this->shelves[$assessmentItemRef] = new AssessmentItemSessionCollection();
     }
     $this->shelves[$assessmentItemRef][$occurence] = $assessmentItemSession;
 }
 public function testGetShuffledChoiceIdentifierAtInvalidShuffledChoiceIndex()
 {
     $doc = new XmlDocument();
     $doc->load(self::samplesDir() . 'ims/items/2_1/choice_fixed.xml');
     $session = new AssessmentItemSession($doc->getDocumentComponent());
     $session->beginItemSession();
     $this->setExpectedException('\\OutOfBoundsException', 'No identifier at index 1337.');
     $session->getShuffledChoiceIdentifierAt(0, 1337);
 }
 public function testAssigningScoresAndCorrectResponses()
 {
     $doc = new XmlDocument();
     $doc->load(self::samplesDir() . 'custom/items/template_processing.xml');
     $session = new AssessmentItemSession($doc->getDocumentComponent());
     $itemSessionControl = new ItemSessionControl();
     $itemSessionControl->setMaxAttempts(0);
     $session->setItemSessionControl($itemSessionControl);
     $session->beginItemSession();
     // Check that the templateProcessing was correctly processed.
     $this->assertEquals('ChoiceA', $session->getVariable('RESPONSE')->getCorrectResponse()->getValue());
     $this->assertEquals(1.0, $session['GOODSCORE']->getValue());
     $this->assertEquals(0.0, $session['WRONGSCORE']->getValue());
     // Check that it really works...
     // With a correct response.
     $session->beginAttempt();
     $responses = new State(array(new ResponseVariable('RESPONSE', Cardinality::SINGLE, BaseType::IDENTIFIER, new QtiIdentifier('ChoiceA'))));
     $session->endAttempt($responses);
     $this->assertEquals(1.0, $session['SCORE']->getValue());
     // With an incorrect response.
     $session->beginAttempt();
     $responses = new State(array(new ResponseVariable('RESPONSE', Cardinality::SINGLE, BaseType::IDENTIFIER, new QtiIdentifier('ChoiceB'))));
     $session->endAttempt($responses);
     $this->assertEquals(0.0, $session['SCORE']->getValue());
 }
 /**
  * Add an item session to the current assessment test session.
  * 
  * @param AssessmentItemSession $session
  * @throws LogicException If the AssessmentItemRef object bound to $session is unknown by the AssessmentTestSession.
  */
 protected function addItemSession(AssessmentItemSession $session, $occurence = 0)
 {
     $assessmentItemRefs = $this->getAssessmentItemRefs();
     $sessionAssessmentItemRefIdentifier = $session->getAssessmentItem()->getIdentifier();
     if ($this->getAssessmentItemRefs()->contains($session->getAssessmentItem()) === false) {
         // The session that is requested to be set is bound to an item
         // which is not referenced in the test. This is a pure logic error.
         $msg = "The item session to set is bound to an unknown AssessmentItemRef.";
         throw new LogicException($msg);
     }
     $this->getAssessmentItemSessionStore()->addAssessmentItemSession($session, $occurence);
 }
 public function testTemplateVariableDefault()
 {
     // This test aims at testing whether template variables
     // are correctly instantiated as part of the item session and
     // they can be used in response processing.
     $doc = new XmlDocument('2.1.0');
     $doc->load(self::samplesDir() . 'custom/items/template_declaration_default.xml');
     $itemSession = new AssessmentItemSession($doc->getDocumentComponent());
     $itemSessionControl = new ItemSessionControl();
     $itemSessionControl->setMaxAttempts(0);
     $itemSession->setItemSessionControl($itemSessionControl);
     $itemSession->beginItemSession();
     $this->assertTrue($itemSession['WRONGSCORE']->equals(new Float(0.0)));
     $this->assertTrue($itemSession['GOODSCORE']->equals(new Float(1.0)));
     // 1st attempt to get 'GOODSCORE' as 'SCORE'.
     $responses = new State(array(new ResponseVariable('RESPONSE', Cardinality::SINGLE, BaseType::IDENTIFIER, new Identifier('ChoiceA'))));
     $itemSession->beginAttempt();
     $itemSession->endAttempt($responses);
     $this->assertTrue($itemSession['SCORE']->equals($itemSession['GOODSCORE']));
     // 2nd attempt to get 'WRONGSCORE' as 'SCORE'.
     $responses = new State(array(new ResponseVariable('RESPONSE', Cardinality::SINGLE, BaseType::IDENTIFIER, new Identifier('ChoiceB'))));
     $itemSession->beginAttempt();
     $itemSession->endAttempt($responses);
     $this->assertTrue($itemSession['SCORE']->equals($itemSession['WRONGSCORE']));
 }
 public function testWriteAssessmentItemSession()
 {
     $doc = new XmlCompactDocument();
     $doc->load(self::samplesDir() . 'custom/runtime/itemsubset.xml');
     $seeker = new AssessmentTestSeeker($doc->getDocumentComponent(), array('assessmentItemRef', 'outcomeDeclaration', 'responseDeclaration', 'itemSessionControl'));
     $stream = new MemoryStream();
     $stream->open();
     $access = new QtiBinaryStreamAccess($stream, new FileSystemFileManager());
     $session = new AssessmentItemSession($doc->getDocumentComponent()->getComponentByIdentifier('Q02'));
     $session->beginItemSession();
     $access->writeAssessmentItemSession($seeker, $session);
     $stream->rewind();
     $session = $access->readAssessmentItemSession(new SessionManager(), $seeker);
     $this->assertEquals(AssessmentItemSessionState::INITIAL, $session->getState());
     $this->assertEquals(NavigationMode::LINEAR, $session->getNavigationMode());
     $this->assertEquals(SubmissionMode::INDIVIDUAL, $session->getSubmissionMode());
     $this->assertEquals('PT0S', $session['duration']->__toString());
     $this->assertEquals(0, $session['numAttempts']->getValue());
     $this->assertEquals('not_attempted', $session['completionStatus']->getValue());
     $this->assertFalse($session->isAttempting());
     $this->assertEquals(0.0, $session['SCORE']->getValue());
     $this->assertTrue($session['RESPONSE']->equals(new MultipleContainer(BaseType::PAIR)));
     $this->assertSame(null, $session->getTimeReference());
     $this->assertFalse($session->hasTimeReference());
 }
 protected static function buildOutcomeResponse(AssessmentItemSession $itemSession)
 {
     $stateOutput = new taoQtiCommon_helpers_PciStateOutput();
     foreach ($itemSession->getOutcomeVariables(false) as $var) {
         $stateOutput->addVariable($var);
     }
     $output = $stateOutput->getOutput();
     return $output;
 }
 protected function submitItemResults(AssessmentItemSession $assessmentItemSession, $occurence = 0)
 {
     foreach ($assessmentItemSession as $id => $var) {
         $this->addItemResultResult($assessmentItemSession->getAssessmentItem()->getIdentifier() . '.' . $occurence . '.' . $id, $var->getValue());
     }
 }
 /**
  * AssessmentTestSession implementations must override this method in order
  * to submit item results from a given $assessmentItemSession to the appropriate
  * data source.
  *
  * This method is triggered each time response processing takes place.
  *
  * @param AssessmentItemSession $itemSession The lastly updated AssessmentItemSession.
  * @param integer $occurrence The occurrence number of the item bound to $assessmentItemSession.
  * @throws AssessmentTestSessionException With error code RESULT_SUBMISSION_ERROR if an error occurs while transmitting results.
  */
 public function submitItemResults(AssessmentItemSession $itemSession, $occurrence = 0)
 {
     $itemRef = $itemSession->getAssessmentItem();
     $identifier = $itemRef->getIdentifier();
     $duration = $this->getTimerDuration($identifier);
     $itemDurationVar = $itemSession->getVariable('duration');
     $sessionDuration = $itemDurationVar->getValue();
     \common_Logger::i("Force duration of item '{$identifier}' to {$duration} instead of {$sessionDuration}");
     $itemSession->getVariable('duration')->setValue($duration);
     parent::submitItemResults($itemSession, $occurrence);
 }
 /**
  * Write an AssessmetnItemSession from the current binary stream.
  * 
  * @param AssessmentTestSeeker $seeker The AssessmentTestSeeker object from where the position of components will be pulled out.
  * @param AssessmentItemSession $session An AssessmentItemSession object.
  * @throws 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()));
         }
         if ($session->getState() !== AssessmentItemSessionState::NOT_SELECTED) {
             $this->writeTinyInt($session['numAttempts']->getValue());
             $this->writeDuration($session['duration']);
             $this->writeString($session['completionStatus']->getValue());
             if ($session['numAttempts']->getValue() > 0) {
                 $this->writeDateTime($session->getTimeReference());
             }
         }
         // minus the 3 built-in variables
         $varCount = count($session) - 3;
         $this->writeTinyInt($varCount);
         $itemOutcomes = $session->getAssessmentItem()->getOutcomeDeclarations();
         $itemResponses = $session->getAssessmentItem()->getResponseDeclarations();
         foreach ($session->getKeys() as $varId) {
             if (in_array($varId, array('numAttempts', 'duration', 'completionStatus')) === false) {
                 $var = $session->getVariable($varId);
                 $isOutcome = $var instanceof OutcomeVariable;
                 $variableDeclaration = $isOutcome === true ? $itemOutcomes[$varId] : $itemResponses[$varId];
                 try {
                     $this->writeBoolean($isOutcome);
                     $this->writeShort($seeker->seekPosition($variableDeclaration));
                     $this->writeVariableValue($var);
                 } catch (OutOfBoundsException $e) {
                     $msg = "No variable found in the assessmentTest tree structure.";
                     throw new QtiBinaryStreamAccessException($msg, $this, QtiBinaryStreamAccessException::ITEM_SESSION, $e);
                 }
             }
         }
     } 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);
     }
 }
Esempio n. 11
0
 /**
  * Get the feedback to be displayed on an AssessmentItemSession
  * 
  * @param tao_models_classes_service_StorageDirectory $directory
  * @param \qtism\runtime\tests\AssessmentItemSession $itemSession
  * @return array 
  */
 public static function getFeedbacks(tao_models_classes_service_StorageDirectory $directory, AssessmentItemSession $itemSession)
 {
     $returnValue = array();
     $feedbackClasses = array('modalFeedback', 'feedbackInline', 'feedbackBlock');
     $elements = self::getContentVariableElements($directory);
     $outcomes = array();
     foreach ($elements as $data) {
         if (empty($data['qtiClass']) === false && in_array($data['qtiClass'], $feedbackClasses)) {
             $feedbackIdentifier = $data['attributes']['identifier'];
             $outcomeIdentifier = $data['attributes']['outcomeIdentifier'];
             if (!isset($outcomes[$outcomeIdentifier])) {
                 $outcomes[$outcomeIdentifier] = array();
             }
             $outcomes[$outcomeIdentifier][$feedbackIdentifier] = $data;
         }
     }
     foreach ($itemSession->getAllVariables() as $var) {
         $identifier = $var->getIdentifier();
         if (isset($outcomes[$identifier])) {
             $feedbacks = $outcomes[$identifier];
             $feedbackIds = QtiRunner::getVariableValues($var);
             foreach ($feedbackIds as $feedbackId) {
                 if (isset($feedbacks[$feedbackId])) {
                     $data = $feedbacks[$feedbackId];
                     $returnValue[$data['serial']] = $data;
                 }
             }
         }
     }
     return $returnValue;
 }
 public function testStandaloneMultipleInteractions()
 {
     $doc = new XmlDocument('2.1');
     $doc->load(self::samplesDir() . 'custom/items/multiple_interactions.xml');
     $itemSession = new AssessmentItemSession($doc->getDocumentComponent(), new SessionManager());
     $itemSession->beginItemSession();
     $itemSession->beginAttempt();
     $this->assertInstanceOf('qtism\\common\\datatypes\\Float', $itemSession['SCORE']);
     $this->assertEquals(0.0, $itemSession['SCORE']->getValue());
     $responses = new State(array(new ResponseVariable('RESPONSE', Cardinality::SINGLE, BaseType::IDENTIFIER, new Identifier('Choice_3'))));
     $itemSession->endAttempt($responses);
     $this->assertEquals(6.0, $itemSession['SCORE']->getValue());
 }
Esempio n. 13
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);
     }
 }
 /**
  * Checks if an item has been completed
  * @param RouteItem $routeItem
  * @param AssessmentItemSession $itemSession
  * @return bool
  */
 public static function isItemCompleted(RouteItem $routeItem, AssessmentItemSession $itemSession)
 {
     $completed = false;
     if ($routeItem->getTestPart()->getNavigationMode() === NavigationMode::LINEAR) {
         // In linear mode, we consider the item completed if it was presented.
         if ($itemSession->isPresented() === true) {
             $completed = true;
         }
     } else {
         // In nonlinear mode we consider:
         // - an adaptive item completed if it's completion status is 'completed'.
         // - a non-adaptive item to be completed if it is responded.
         $isAdaptive = $itemSession->getAssessmentItem()->isAdaptive();
         if ($isAdaptive === true && $itemSession['completionStatus']->getValue() === AssessmentItemSession::COMPLETION_STATUS_COMPLETED) {
             $completed = true;
         } else {
             if ($isAdaptive === false && $itemSession->isResponded() === true) {
                 $completed = true;
             }
         }
     }
     return $completed;
 }