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()); }