/** * Register all needed information about the AssessmentSection involved in a given * $routeItem. * * @param \qtism\runtime\tests\RouteItem $routeItem A RouteItem object. */ protected function registerAssessmentSection(RouteItem $routeItem) { foreach ($routeItem->getAssessmentSections() as $assessmentSection) { if (isset($this->assessmentSectionMap[$assessmentSection]) === false) { $this->assessmentSectionMap[$assessmentSection] = array(); } $target = $this->assessmentSectionMap[$assessmentSection]; $target[] = $routeItem; $this->assessmentSectionMap[$assessmentSection] = $target; // Register the RouteItem in the assessmentSectionIdentifierMap. $id = $assessmentSection->getIdentifier(); if (isset($this->assessmentSectionIdentifierMap[$id]) === false) { $assessmentSectionIdentifierMap[$id] = array(); } $this->assessmentSectionIdentifierMap[$id][] = $routeItem; } }
/** * Gets the item tags for its last occurrence * @param RouteItem $routeItem * @return string */ public function getItemAttemptTag(RouteItem $routeItem) { $itemRef = $routeItem->getAssessmentItemRef(); $itemId = $itemRef->getIdentifier(); $occurrence = $routeItem->getOccurence(); $itemSession = $this->getAssessmentItemSessionStore()->getAssessmentItemSession($itemRef, $occurrence); return $itemId . '#' . $occurrence . '-' . $itemSession['numAttempts']->getValue(); }
/** * Save session metadata. * * @param array $metaData Meta data array to be saved. * @param RouteItem $routeItem item for which data will be saved * @param string $assessmentSectionId section id for which data will be saved * Example: * array( * 'TEST' => array('TEST_EXIT_CODE' => 'IC'), * 'SECTION' => array('SECTION_EXIT_CODE' => 701), * ) */ public function save(array $metaData, RouteItem $routeItem = null, $assessmentSectionId = null) { $testUri = $this->session->getTest()->getUri(); $resultServer = \taoResultServer_models_classes_ResultServerStateFull::singleton(); foreach ($metaData as $type => $data) { foreach ($data as $key => $value) { $metaVariable = $this->getVariable($key, $value); if (strcasecmp($type, 'ITEM') === 0) { if ($routeItem === null) { $itemRef = $this->session->getCurrentAssessmentItemRef(); $occurence = $this->session->getCurrentAssessmentItemRefOccurence(); } else { $itemRef = $routeItem->getAssessmentItemRef(); $occurence = $routeItem->getOccurence(); } $itemUri = $this->getItemUri($itemRef); $sessionId = $this->session->getSessionId(); $transmissionId = "{$sessionId}.{$itemRef}.{$occurence}"; $resultServer->storeItemVariable($testUri, $itemUri, $metaVariable, $transmissionId); } elseif (strcasecmp($type, 'TEST') === 0) { $resultServer->storeTestVariable($testUri, $metaVariable, $this->session->getSessionId()); } elseif (strcasecmp($type, 'SECTION') === 0) { //suffix section variables with _{SECTION_IDENTIFIER} if ($assessmentSectionId === null) { $assessmentSectionId = $this->session->getCurrentAssessmentSection()->getIdentifier(); } $metaVariable->setIdentifier($key . '_' . $assessmentSectionId); $resultServer->storeTestVariable($testUri, $metaVariable, $this->session->getSessionId()); } } } }
/** * Write a route item in the current binary stream. * * @param AssessmentTestSeeker $seeker An AssessmentTestSeeker object in order to know tree position for involved QTI Components. * @param RouteItem $routeItem A RouteItem object. * @throws QtiBinaryStreamAccessException */ public function writeRouteItem(AssessmentTestSeeker $seeker, RouteItem $routeItem) { try { $this->writeTinyInt($routeItem->getOccurence()); $this->writeShort($seeker->seekPosition($routeItem->getAssessmentItemRef())); if (QtiBinaryConstants::QTI_BINARY_STORAGE_VERSION <= 2) { // Prior to version 3, only a single assessmentSection might be bound // to the RouteItem. $this->writeShort($seeker->seekPosition($routeItem->getAssessmentSection())); } $this->writeShort($seeker->seekPosition($routeItem->getTestPart())); if (QtiBinaryConstants::QTI_BINARY_STORAGE_VERSION >= 3) { $assessmentSections = $routeItem->getAssessmentSections(); // From version 3, multiple assessmentSections might be bound // to the RouteItem. $this->writeTinyInt(count($assessmentSections)); foreach ($assessmentSections as $assessmentSection) { $this->writeShort($seeker->seekPosition($assessmentSection)); } } $branchRules = $routeItem->getBranchRules(); $this->writeTinyInt(count($branchRules)); foreach ($branchRules as $branchRule) { $this->writeShort($seeker->seekPosition($branchRule)); } $preConditions = $routeItem->getPreConditions(); $this->writeTinyInt(count($preConditions)); foreach ($preConditions as $preCondition) { $this->writeShort($seeker->seekPosition($preCondition)); } } catch (BinaryStreamAccessException $e) { $msg = "An error occured while writing a route item."; throw new QtiBinaryStreamAccessException($msg, $this, QtiBinaryStreamAccessException::ROUTE_ITEM, $e); } catch (OutOfBoundsException $e) { $msg = "A QTI Component position was not found in the assessmentTest tree structure."; throw new QtiBinaryStreamAccessException($msg, $this, QtiBinaryStreamAccessException::ROUTE_ITEM, $e); } }
/** * Write a route item in the current binary stream. * * @param \qtism\runtime\storage\common\AssessmentTestSeeker $seeker An AssessmentTestSeeker object in order to know tree position for involved QTI Components. * @param \qtism\runtime\tests\RouteItem $routeItem A RouteItem object. * @throws \qtism\runtime\storage\binary\QtiBinaryStreamAccessException */ public function writeRouteItem(AssessmentTestSeeker $seeker, RouteItem $routeItem) { try { $this->writeTinyInt($routeItem->getOccurence()); $this->writeShort($seeker->seekPosition($routeItem->getAssessmentItemRef())); $this->writeShort($seeker->seekPosition($routeItem->getTestPart())); $assessmentSections = $routeItem->getAssessmentSections(); $this->writeTinyInt(count($assessmentSections)); foreach ($assessmentSections as $assessmentSection) { $this->writeShort($seeker->seekPosition($assessmentSection)); } $branchRules = $routeItem->getBranchRules(); $this->writeTinyInt(count($branchRules)); foreach ($branchRules as $branchRule) { $this->writeShort($seeker->seekPosition($branchRule)); } $preConditions = $routeItem->getPreConditions(); $this->writeTinyInt(count($preConditions)); foreach ($preConditions as $preCondition) { $this->writeShort($seeker->seekPosition($preCondition)); } } catch (BinaryStreamAccessException $e) { $msg = "An error occured while writing a route item."; throw new QtiBinaryStreamAccessException($msg, $this, QtiBinaryStreamAccessException::ROUTE_ITEM, $e); } catch (OutOfBoundsException $e) { $msg = "A QTI Component position was not found in the assessmentTest tree structure."; throw new QtiBinaryStreamAccessException($msg, $this, QtiBinaryStreamAccessException::ROUTE_ITEM, $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; }