/**
  * 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;
 }