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());
 }
 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);
 }
 /**
  * Item's ResponseProcessing.
  *
  * @param core_kernel_classes_Resource $item The Item you want to apply ResponseProcessing.
  * @throws \RuntimeException If an error occurs while processing responses or transmitting results
  */
 protected function processResponses(core_kernel_classes_Resource $item)
 {
     $jsonPayload = taoQtiCommon_helpers_Utils::readJsonPayload();
     try {
         $qtiXmlFilePath = QtiFile::getQtiFilePath($item);
         $qtiXmlDoc = new XmlDocument();
         $qtiXmlDoc->load($qtiXmlFilePath);
     } catch (StorageException $e) {
         $msg = "An error occurred while loading QTI-XML file at expected location '{$qtiXmlFilePath}'.";
         common_Logger::e($e->getPrevious()->getMessage());
         throw new \RuntimeException($msg, 0, $e);
     }
     $itemSession = new AssessmentItemSession($qtiXmlDoc->getDocumentComponent(), new SessionManager());
     $itemSession->beginItemSession();
     $variables = array();
     $filler = new taoQtiCommon_helpers_PciVariableFiller($qtiXmlDoc->getDocumentComponent());
     // Convert client-side data as QtiSm Runtime Variables.
     foreach ($jsonPayload as $id => $response) {
         try {
             $var = $filler->fill($id, $response);
             // Do not take into account QTI Files at preview time.
             // Simply delete the created file.
             if (taoQtiCommon_helpers_Utils::isQtiFile($var, false) === true) {
                 $fileManager = taoQtiCommon_helpers_Utils::getFileDatatypeManager();
                 $fileManager->delete($var->getValue());
             } else {
                 $variables[] = $var;
             }
         } catch (OutOfRangeException $e) {
             // A variable value could not be converted, ignore it.
             // Developer's note: QTI Pairs with a single identifier (missing second identifier of the pair) are transmitted as an array of length 1,
             // this might cause problem. Such "broken" pairs are simply ignored.
             common_Logger::d("Client-side value for variable '{$id}' is ignored due to data malformation.");
         } catch (OutOfBoundsException $e) {
             // No such identifier found in item.
             common_Logger::d("The variable with identifier '{$id}' is not declared in the item definition.");
         }
     }
     try {
         $itemSession->beginAttempt();
         $itemSession->endAttempt(new State($variables));
         // Return the item session state to the client-side.
         echo json_encode(array('success' => true, 'displayFeedback' => true, 'itemSession' => self::buildOutcomeResponse($itemSession)));
     } catch (AssessmentItemSessionException $e) {
         $msg = "An error occurred while processing the responses.";
         throw new \RuntimeException($msg, 0, $e);
     } catch (taoQtiCommon_helpers_ResultTransmissionException $e) {
         $msg = "An error occurred while transmitting a result to the target Result Server.";
         throw new \RuntimeException($msg, 0, $e);
     }
 }
 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());
 }
 /**
  * Item's ResponseProcessing.
  * 
  * @param core_kernel_file_File $itemPath The Item file resource you want to apply ResponseProcessing.
  * @throws RuntimeException If an error occurs while processing responses or transmitting results
  */
 protected function processResponses(core_kernel_classes_Resource $item)
 {
     $jsonPayload = taoQtiCommon_helpers_Utils::readJsonPayload();
     try {
         $qtiXmlFileContent = QtiFile::getQtiFileContent($item);
         $qtiXmlDoc = new XmlDocument();
         $qtiXmlDoc->loadFromString($qtiXmlFileContent);
     } catch (StorageException $e) {
         $msg = "An error occured while loading QTI-XML file at expected location '{$qtiXmlFilePath}'.";
         throw new \RuntimeException($msg, 0, $e);
     }
     $itemSession = new AssessmentItemSession($qtiXmlDoc->getDocumentComponent(), new SessionManager());
     $itemSession->beginItemSession();
     $variables = array();
     // Convert client-side data as QtiSm Runtime Variables.
     foreach ($jsonPayload as $identifier => $response) {
         $filler = new taoQtiCommon_helpers_PciVariableFiller($qtiXmlDoc->getDocumentComponent());
         try {
             $var = $filler->fill($identifier, $response);
             // Do not take into account QTI File placeholders.
             if (taoQtiCommon_helpers_Utils::isQtiFilePlaceHolder($var) === false) {
                 $variables[] = $var;
             }
         } catch (\OutOfRangeException $e) {
             // A variable value could not be converted, ignore it.
             // Developer's note: QTI Pairs with a single identifier (missing second identifier of the pair) are transmitted as an array of length 1,
             // this might cause problem. Such "broken" pairs are simply ignored.
             common_Logger::d("Client-side value for variable '{$identifier}' is ignored due to data malformation.");
         } catch (\OutOfBoundsException $e) {
             // The response identifier does not match any response declaration.
             common_Logger::d("Uknown item variable declaration '{$identifier}.");
         }
     }
     try {
         $itemSession->beginAttempt();
         $itemSession->endAttempt(new State($variables));
         // Transmit results to the Result Server.
         $this->transmitResults($item, $itemSession);
         // Return the item session state to the client-side.
         echo json_encode(array('success' => true, 'displayFeedback' => true, 'itemSession' => self::buildOutcomeResponse($itemSession), 'feedbacks' => $this->getFeedbacks($itemSession)));
     } catch (AssessmentItemSessionException $e) {
         $msg = "An error occured while processing the responses.";
         throw new \RuntimeException($msg, 0, $e);
     } catch (taoQtiCommon_helpers_ResultTransmissionException $e) {
         $msg = "An error occured while transmitting variable '{$identifier}' to the target Result Server.";
         throw new \RuntimeException($msg, 0, $e);
     }
 }
 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());
 }