/** * Builds the map of an assessment test * @param RunnerServiceContext $context The test context * @param RunnerConfig $config The runner config * @return mixed */ public function getMap(RunnerServiceContext $context, RunnerConfig $config) { $map = ['parts' => [], 'jumps' => []]; // get config for the sequence number option $reviewConfig = $config->getConfigValue('review'); $checkInformational = $config->getConfigValue('checkInformational'); $forceTitles = !empty($reviewConfig['forceTitle']); $uniqueTitle = isset($reviewConfig['itemTitle']) ? $reviewConfig['itemTitle'] : '%d'; /* @var AssessmentTestSession $session */ $session = $context->getTestSession(); if ($session->isRunning() !== false) { $route = $session->getRoute(); $store = $session->getAssessmentItemSessionStore(); $routeItems = $route->getAllRouteItems(); $offset = $route->getRouteItemPosition($routeItems[0]); $offsetPart = 0; $offsetSection = 0; $lastPart = null; $lastSection = null; /** @var \qtism\runtime\tests\RouteItem $routeItem */ foreach ($routeItems as $routeItem) { // access the item reference $itemRef = $routeItem->getAssessmentItemRef(); $occurrence = $routeItem->getOccurence(); // get the jump definition $itemSession = $store->getAssessmentItemSession($itemRef, $occurrence); // load item infos $testPart = $routeItem->getTestPart(); $partId = $testPart->getIdentifier(); $section = $routeItem->getAssessmentSection(); $sectionId = $section->getIdentifier(); $itemId = $itemRef->getIdentifier(); $itemUri = strstr($itemRef->getHref(), '|', true); $item = new \core_kernel_classes_Resource($itemUri); if ($lastPart != $partId) { $offsetPart = 0; $lastPart = $partId; } if ($lastSection != $sectionId) { $offsetSection = 0; $lastSection = $sectionId; } if ($forceTitles) { $label = sprintf($uniqueTitle, $offsetSection + 1); } else { $label = $item->getLabel(); } $itemInfos = ['id' => $itemId, 'uri' => $itemUri, 'label' => $label, 'position' => $offset, 'positionInPart' => $offsetPart, 'positionInSection' => $offsetSection, 'index' => $offsetSection + 1, 'occurrence' => $occurrence, 'remainingAttempts' => $itemSession->getRemainingAttempts(), 'answered' => TestRunnerUtils::isItemCompleted($routeItem, $itemSession), 'flagged' => TestRunnerUtils::getItemFlag($session, $routeItem), 'viewed' => $itemSession->isPresented()]; if ($checkInformational) { $itemInfos['informational'] = TestRunnerUtils::isItemInformational($routeItem, $itemSession); } // update the map $map['jumps'][] = ['identifier' => $itemId, 'section' => $sectionId, 'part' => $partId, 'position' => $offset, 'uri' => $itemUri]; if (!isset($map['parts'][$partId])) { $map['parts'][$partId]['id'] = $partId; $map['parts'][$partId]['label'] = $partId; $map['parts'][$partId]['position'] = $offset; $map['parts'][$partId]['isLinear'] = $testPart->getNavigationMode() == NavigationMode::LINEAR; } if (!isset($map['parts'][$partId]['sections'][$sectionId])) { $map['parts'][$partId]['sections'][$sectionId]['id'] = $sectionId; $map['parts'][$partId]['sections'][$sectionId]['label'] = $section->getTitle(); $map['parts'][$partId]['sections'][$sectionId]['position'] = $offset; } $map['parts'][$partId]['sections'][$sectionId]['items'][$itemId] = $itemInfos; // update the stats $this->updateStats($map, $itemInfos); $this->updateStats($map['parts'][$partId], $itemInfos); $this->updateStats($map['parts'][$partId]['sections'][$sectionId], $itemInfos); $offset++; $offsetPart++; $offsetSection++; } } return $map; }