예제 #1
0
 /**
  * Display the session history of the current test center
  */
 public function sessionHistory()
 {
     $testCenter = $this->getCurrentTestCenter();
     $delivery = $this->getCurrentDelivery(false);
     $sessions = $this->getRequestParameter('session');
     $requestOptions = $this->getRequestOptions(['sortby' => 'timestamp', 'sortorder' => 'desc', 'periodStart' => '', 'periodEnd' => '', 'detailed' => false]);
     if (!is_array($sessions)) {
         $sessions = $sessions ? explode(',', $sessions) : [];
     }
     $breadcrumbs = [BreadcrumbsHelper::testCenters(), BreadcrumbsHelper::testCenter($testCenter, TestCenterHelper::getTestCenters()), BreadcrumbsHelper::deliveries($testCenter, [BreadcrumbsHelper::diagnostics($testCenter)])];
     $viewData = ['testCenter' => $testCenter->getUri(), 'set' => TestCenterHelper::getSessionHistory($sessions, true, $requestOptions), 'sessions' => $sessions, 'sortBy' => $requestOptions['sortBy'], 'sortOrder' => $requestOptions['sortOrder'], 'periodStart' => $requestOptions['periodStart'], 'periodEnd' => $requestOptions['periodEnd']];
     if ($delivery) {
         $breadcrumbs[] = BreadcrumbsHelper::deliveryMonitoring($testCenter, $delivery, DeliveryHelper::getDeliveries($testCenter));
         $viewData['delivery'] = $delivery->getUri();
     } else {
         $breadcrumbs[] = BreadcrumbsHelper::deliveryMonitoringAll($testCenter, DeliveryHelper::getDeliveries($testCenter));
     }
     $breadcrumbs[] = BreadcrumbsHelper::sessionHistory($testCenter, $delivery, $sessions);
     if (count($sessions) > 1) {
         $title = __('Detailed Session History of a selection');
     } else {
         $deliveryExecution = \taoDelivery_models_classes_execution_ServiceProxy::singleton()->getDeliveryExecution($sessions[0]);
         $title = __('Detailed Session History of %s', $deliveryExecution->getLabel());
     }
     $this->setData('title', $title);
     $this->composeView('session-history', $viewData, $breadcrumbs);
 }
 /**
  * Get the requested delivery resource
  * Use this to identify which delivery is currently being selected buy the proctor
  *
  * @param bool $mandatory Throws an exception if the delivery is not provided
  * @return core_kernel_classes_Resource
  * @throws \common_Exception
  */
 protected function getCurrentDelivery($mandatory = true)
 {
     if (is_null($this->currentDelivery)) {
         if ($this->hasRequestParameter('delivery')) {
             //get test center resource from its uri
             $deliveryUri = $this->getRequestParameter('delivery');
             $this->currentDelivery = DeliveryHelper::getDelivery($deliveryUri);
         } else {
             if ($mandatory) {
                 //@todo use a better exception
                 throw new \common_Exception('no current delivery');
             }
         }
     }
     return $this->currentDelivery;
 }
 public static function propertyChange(MetadataModified $event)
 {
     $resource = $event->getResource();
     $service = ServiceManager::getServiceManager()->get(DeliveryMonitoringService::CONFIG_ID);
     $tracked = array_merge([PROPERTY_USER_FIRSTNAME, PROPERTY_USER_LASTNAME], array_map(function ($field) {
         return $field['property']->getUri();
     }, DeliveryHelper::getExtraFieldsProperties()));
     if (in_array($event->getMetadataUri(), $tracked) && $resource->hasType(new \core_kernel_classes_Class(TAO_CLASS_SUBJECT))) {
         $deliveryExecutionsData = $service->find([DeliveryMonitoringService::TEST_TAKER => $resource->getUri()], []);
         foreach ($deliveryExecutionsData as $data) {
             $data->updateData([DeliveryMonitoringService::TEST_TAKER, DeliveryMonitoringService::TEST_TAKER_FIRST_NAME, DeliveryMonitoringService::TEST_TAKER_LAST_NAME]);
             $success = $service->save($data);
             if (!$success) {
                 \common_Logger::w('monitor cache for delivery ' . $data[DeliveryMonitoringService::DELIVERY_EXECUTION_ID] . ' could not be updated. TestTaker data has not been changed');
             }
         }
     }
 }
예제 #4
0
 /**
  * Extra Time handling: add or remove time on delivery executions
  * 
  * @throws \common_Exception
  */
 public function extraTime()
 {
     $deliveryExecution = $this->getRequestParameter('execution');
     $extraTime = floatval($this->getRequestParameter('time'));
     if (!is_array($deliveryExecution)) {
         $deliveryExecution = array($deliveryExecution);
     }
     try {
         $reported = DeliveryHelper::setExtraTime($deliveryExecution, $extraTime);
         $notReported = array_diff($deliveryExecution, $reported);
         $this->returnJson(array('success' => !count($notReported), 'processed' => $reported, 'unprocessed' => $notReported));
     } catch (ServiceNotFoundException $e) {
         \common_Logger::w('No delivery service defined for proctoring');
         $this->returnError('Proctoring interface not available');
     }
 }
 /**
  * @deprecated please use DeliveryHelper
  */
 public function setHasBeenPaused($deliveryExecution)
 {
     return DeliveryHelper::setHasBeenPaused($deliveryExecution);
 }
$i = 0;
$proctorNum = 1;
$ttNum = 1;
$subClass = $testTakerService->createSubClass($testTakerService->getRootClass(), 'jmeter_test_taker_' . $totalTtNum);
while ($i < $totalProctorNum) {
    if ($userService->loginAvailable('Jmeter_proctor_' . $proctorNum)) {
        $tts = array();
        //create sample group
        $testCenter = $testCenterService->createInstance(new \core_kernel_classes_Class($testCenterService::CLASS_URI), 'jmeter_test_center_' . $proctorNum);
        $proctor = $userService->addUser('Jmeter_proctor_' . $proctorNum, 'Jmeter_proctor_' . $proctorNum, new \core_kernel_classes_Resource("http://www.tao.lu/Ontologies/TAOProctor.rdf#ProctorRole"), $userClass);
        $proctor->setPropertyValue(new core_kernel_classes_Property($proctorManagementService::PROPERTY_ASSIGNED_PROCTOR_URI), $testCenter);
        $proctor->setPropertyValue(new core_kernel_classes_Property($proctorManagementService::PROPERTY_ADMINISTRATOR_URI), $testCenter);
        $i++;
        $j = 0;
        while ($j < $ttByProctor) {
            if ($userService->loginAvailable('jmeter_TT_' . $ttNum)) {
                $tt = $testTakerCrudService->createFromArray(array(PROPERTY_USER_LOGIN => 'jmeter_TT_' . $ttNum, PROPERTY_USER_PASSWORD => 'jmeter_TT_' . $ttNum, RDFS_LABEL => 'jmeter_tt' . $ttNum, PROPERTY_USER_FIRSTNAME => 'jmeter_tt_' . $ttNum, PROPERTY_USER_LASTNAME => 'jmeter_tt_' . $ttNum, RDF_TYPE => $subClass));
                $tts[] = $tt->getUri();
                $j++;
            }
            $ttNum++;
        }
        $testCenterService->addTestTaker($tt->getUri(), $testCenter);
        //add delivery to eligible list
        \oat\taoProctoring\model\EligibilityService::singleton()->createEligibility($testCenter, $delivery);
        \oat\taoProctoring\model\EligibilityService::singleton()->setEligibleTestTakers($testCenter, $delivery, $tts);
        //assign tt to delivery
        \oat\taoProctoring\helpers\DeliveryHelper::assignTestTakers($tts, $delivery->getUri(), $testCenter->getUri());
    }
    $proctorNum++;
}
 /**
  * @param string $sortBy
  * @return string
  */
 public static function getSortByColumn($sortBy)
 {
     $map = array_merge(['firstname' => self::COLUMN_TEST_TAKER_FIRST_NAME, 'lastname' => self::TEST_TAKER_LAST_NAME, 'delivery' => self::DELIVERY_NAME, 'status' => self::STATUS, 'connectivity' => self::CONNECTIVITY], array_combine(array_map(function ($property) {
         return strtolower($property['id']);
     }, DeliveryHelper::getExtraFields()), array_map(function ($property) {
         return $property['id'];
     }, DeliveryHelper::getExtraFields())));
     return array_key_exists(strtolower($sortBy), $map) ? $map[strtolower($sortBy)] : self::DEFAULT_SORT_COLUMN;
 }
 /**
  * @param bool $overwrite
  */
 private function addExtraFieldsValues($overwrite = false)
 {
     $user = $this->getUser();
     if ($user) {
         $fields = DeliveryHelper::getExtraFieldsProperties();
         foreach ($fields as $field) {
             $values = $user->getPropertyValues($field['property']);
             if (!empty($values) && is_array($values)) {
                 $this->addValue($field['id'], (string) $values[0], $overwrite);
             }
         }
     }
 }
 /**
  * Build the context of the given candidate test $session as an associative array. This array
  * is especially usefull to transmit the test context to a view as JSON data.
  * 
  * The returned array contains the following keys:
  * 
  * * state: The state of test session.
  * * navigationMode: The current navigation mode.
  * * submissionMode: The current submission mode.
  * * remainingAttempts: The number of remaining attempts for the current item.
  * * isAdaptive: Whether or not the current item is adaptive.
  * * itemIdentifier: The identifier of the current item.
  * * itemSessionState: The state of the current assessment item session.
  * * timeConstraints: The time constraints in force.
  * * testTitle: The title of the test.
  * * testPartId: The identifier of the current test part.
  * * sectionTitle: The title of the current section.
  * * numberItems: The total number of items eligible to the candidate.
  * * numberCompleted: The total number items considered to be completed by the candidate.
  * * moveForwardUrl: The URL to be dereferenced to perform a moveNext on the session.
  * * moveBackwardUrl: The URL to be dereferenced to perform a moveBack on the session.
  * * skipUrl: The URL to be dereferenced to perform a skip on the session.
  * * commentUrl: The URL to be dereferenced to leave a comment about the current item.
  * * timeoutUrl: The URL to be dereferenced when the time constraints in force reach their maximum.
  * * canMoveBackward: Whether or not the candidate is allowed/able to move backward.
  * * jumps: The possible jumpers the candidate is allowed to undertake among eligible items.
  * * itemServiceApiCall: The JavaScript code to be executed to instantiate the current item.
  * * rubrics: The XHTML compiled content of the rubric blocks to be displayed for the current item if any.
  * * allowComment: Whether or not the candidate is allowed to leave a comment about the current item.
  * * allowSkipping: Whether or not the candidate is allowed to skip the current item.
  * * considerProgress: Whether or not the test driver view must consider to give a test progress feedback.
  * 
  * @param AssessmentTestSession $session A given AssessmentTestSession object.
  * @param array $testMeta An associative array containing meta-data about the test definition taken by the candidate.
  * @param string $qtiTestDefinitionUri The URI of a reference to an Assessment Test definition in the knowledge base.
  * @param string $qtiTestCompilationUri The Uri of a reference to an Assessment Test compilation in the knowledge base.
  * @param string $standalone
  * @param string $compilationDirs An array containing respectively the private and public compilation directories.
  * @return array The context of the candidate session.
  */
 public static function buildAssessmentTestContext(AssessmentTestSession $session, array $testMeta, $qtiTestDefinitionUri, $qtiTestCompilationUri, $standalone, $compilationDirs)
 {
     $context = array();
     // The state of the test session.
     $context['state'] = $session->getState();
     // Default values for the test session context.
     $context['navigationMode'] = null;
     $context['submissionMode'] = null;
     $context['remainingAttempts'] = 0;
     $context['isAdaptive'] = false;
     $hasBeenPaused = false;
     if (common_ext_ExtensionsManager::singleton()->isEnabled('taoProctoring')) {
         $hasBeenPaused = \oat\taoProctoring\helpers\DeliveryHelper::getHasBeenPaused($session->getSessionId());
     }
     $context['hasBeenPaused'] = $hasBeenPaused;
     if ($session->getState() === AssessmentTestSessionState::INTERACTING) {
         $config = common_ext_ExtensionsManager::singleton()->getExtensionById('taoQtiTest')->getConfig('testRunner');
         // The navigation mode.
         $context['navigationMode'] = $session->getCurrentNavigationMode();
         // The submission mode.
         $context['submissionMode'] = $session->getCurrentSubmissionMode();
         // The number of remaining attempts for the current item.
         $context['remainingAttempts'] = $session->getCurrentRemainingAttempts();
         // Whether or not the current step is time out.
         $context['isTimeout'] = self::isTimeout($session);
         // The identifier of the current item.
         $context['itemIdentifier'] = $session->getCurrentAssessmentItemRef()->getIdentifier();
         // The state of the current AssessmentTestSession.
         $context['itemSessionState'] = $session->getCurrentAssessmentItemSession()->getState();
         // Whether the current item is adaptive.
         $context['isAdaptive'] = $session->isCurrentAssessmentItemAdaptive();
         // Whether the current item is the very last one of the test.
         $context['isLast'] = $session->getRoute()->isLast();
         // The current position in the route.
         $context['itemPosition'] = $session->getRoute()->getPosition();
         // Time constraints.
         $context['timeConstraints'] = self::buildTimeConstraints($session);
         // Test title.
         $context['testTitle'] = $session->getAssessmentTest()->getTitle();
         // Test Part title.
         $context['testPartId'] = $session->getCurrentTestPart()->getIdentifier();
         // Current Section title.
         $context['sectionTitle'] = $session->getCurrentAssessmentSection()->getTitle();
         // Number of items composing the test session.
         $context['numberItems'] = $session->getRouteCount(AssessmentTestSession::ROUTECOUNT_FLOW);
         // Number of items completed during the test session.
         $context['numberCompleted'] = self::testCompletion($session);
         // Number of items presented during the test session.
         $context['numberPresented'] = $session->numberPresented();
         // Whether or not the progress of the test can be inferred.
         $context['considerProgress'] = self::considerProgress($session, $testMeta, $config);
         // Whether or not the deepest current section is visible.
         $context['isDeepestSectionVisible'] = $session->getCurrentAssessmentSection()->isVisible();
         // The URLs to be called to move forward/backward in the Assessment Test Session or skip or comment.
         $context['moveForwardUrl'] = self::buildActionCallUrl($session, 'moveForward', $qtiTestDefinitionUri, $qtiTestCompilationUri, $standalone);
         $context['moveBackwardUrl'] = self::buildActionCallUrl($session, 'moveBackward', $qtiTestDefinitionUri, $qtiTestCompilationUri, $standalone);
         $context['nextSectionUrl'] = self::buildActionCallUrl($session, 'nextSection', $qtiTestDefinitionUri, $qtiTestCompilationUri, $standalone);
         $context['skipUrl'] = self::buildActionCallUrl($session, 'skip', $qtiTestDefinitionUri, $qtiTestCompilationUri, $standalone);
         $context['commentUrl'] = self::buildActionCallUrl($session, 'comment', $qtiTestDefinitionUri, $qtiTestCompilationUri, $standalone);
         $context['timeoutUrl'] = self::buildActionCallUrl($session, 'timeout', $qtiTestDefinitionUri, $qtiTestCompilationUri, $standalone);
         $context['endTestSessionUrl'] = self::buildActionCallUrl($session, 'endTestSession', $qtiTestDefinitionUri, $qtiTestCompilationUri, $standalone);
         $context['keepItemTimedUrl'] = self::buildActionCallUrl($session, 'keepItemTimed', $qtiTestDefinitionUri, $qtiTestCompilationUri, $standalone);
         // If the candidate is allowed to move backward e.g. first item of the test.
         $context['canMoveBackward'] = $session->canMoveBackward();
         // The places in the test session where the candidate is allowed to jump to.
         $context['jumps'] = self::buildPossibleJumps($session);
         // The test review screen setup
         if (!empty($config['test-taker-review']) && $context['considerProgress']) {
             // The navigation map in order to build the test navigator
             $navigator = self::getNavigatorMap($session);
             if ($navigator !== NavigationMode::LINEAR) {
                 $context['navigatorMap'] = $navigator['map'];
                 $context['itemFlagged'] = self::getItemFlag($session, $context['itemPosition']);
             } else {
                 $navigator = self::countItems($session);
             }
             // Extract the progression stats
             $context['numberFlagged'] = $navigator['numberItemsFlagged'];
             $context['numberItemsPart'] = $navigator['numberItemsPart'];
             $context['numberItemsSection'] = $navigator['numberItemsSection'];
             $context['numberCompletedPart'] = $navigator['numberCompletedPart'];
             $context['numberCompletedSection'] = $navigator['numberCompletedSection'];
             $context['numberPresentedPart'] = $navigator['numberPresentedPart'];
             $context['numberPresentedSection'] = $navigator['numberPresentedSection'];
             $context['numberFlaggedPart'] = $navigator['numberFlaggedPart'];
             $context['numberFlaggedSection'] = $navigator['numberFlaggedSection'];
             $context['itemPositionPart'] = $navigator['itemPositionPart'];
             $context['itemPositionSection'] = $navigator['itemPositionSection'];
             // The URLs to be called to move to a particular item in the Assessment Test Session or mark item for later review.
             $context['jumpUrl'] = self::buildActionCallUrl($session, 'jumpTo', $qtiTestDefinitionUri, $qtiTestCompilationUri, $standalone);
             $context['markForReviewUrl'] = self::buildActionCallUrl($session, 'markForReview', $qtiTestDefinitionUri, $qtiTestCompilationUri, $standalone);
         } else {
             // Setup data for progress bar when displaying position and timed section exit control
             $numberItems = self::countItems($session);
             $context['numberCompletedPart'] = $numberItems['numberCompletedPart'];
             $context['numberCompletedSection'] = $numberItems['numberCompletedSection'];
             $context['numberItemsSection'] = $numberItems['numberItemsSection'];
             $context['numberItemsPart'] = $numberItems['numberItemsPart'];
             $context['itemPositionPart'] = $numberItems['itemPositionPart'];
             $context['itemPositionSection'] = $numberItems['itemPositionSection'];
         }
         // The code to be executed to build the ServiceApi object to be injected in the QTI Item frame.
         $context['itemServiceApiCall'] = self::buildServiceApi($session, $qtiTestDefinitionUri, $qtiTestCompilationUri);
         // Rubric Blocks.
         $rubrics = array();
         // -- variables used in the included rubric block templates.
         // base path (base URI to be used for resource inclusion).
         $basePathVarName = TAOQTITEST_BASE_PATH_NAME;
         ${$basePathVarName} = $compilationDirs['public']->getPublicAccessUrl();
         // state name (the variable to access to get the state of the assessmentTestSession).
         $stateName = TAOQTITEST_RENDERING_STATE_NAME;
         ${$stateName} = $session;
         // views name (the variable to be accessed for the visibility of rubric blocks).
         $viewsName = TAOQTITEST_VIEWS_NAME;
         ${$viewsName} = array(View::CANDIDATE);
         foreach ($session->getRoute()->current()->getRubricBlockRefs() as $rubric) {
             $data = $compilationDirs['private']->read($rubric->getHref());
             $tmpDir = \tao_helpers_File::createTempDir();
             $tmpFile = $tmpDir . basename($rubric->getHref());
             file_put_contents($tmpFile, $data);
             ob_start();
             include $tmpFile;
             $rubrics[] = ob_get_clean();
             unlink($tmpFile);
             rmdir($tmpDir);
         }
         $context['rubrics'] = $rubrics;
         // Comment allowed? Skipping allowed? Logout or Exit allowed ?
         $context['allowComment'] = self::doesAllowComment($session);
         $context['allowSkipping'] = self::doesAllowSkipping($session);
         $context['exitButton'] = self::doesAllowExit($session);
         $context['logoutButton'] = self::doesAllowLogout($session);
         $context['categories'] = self::getCategories($session);
         // loads the specific config into the context object
         $configMap = array('timerWarning' => 'timerWarning', 'progress-indicator' => 'progressIndicator', 'progress-indicator-scope' => 'progressIndicatorScope', 'test-taker-review' => 'reviewScreen', 'test-taker-review-region' => 'reviewRegion', 'test-taker-review-scope' => 'reviewScope', 'test-taker-review-prevents-unseen' => 'reviewPreventsUnseen', 'test-taker-review-can-collapse' => 'reviewCanCollapse', 'next-section' => 'nextSection', 'keep-timer-up-to-timeout' => 'keepTimerUpToTimeout');
         foreach ($configMap as $configKey => $contextKey) {
             if (isset($config[$configKey])) {
                 $context[$contextKey] = $config[$configKey];
             }
         }
         // optionally extend the context
         if (isset($config['extraContextBuilder']) && class_exists($config['extraContextBuilder'])) {
             $builder = new $config['extraContextBuilder']();
             if ($builder instanceof \oat\taoQtiTest\models\TestContextBuilder) {
                 $builder->extendAssessmentTestContext($context, $session, $testMeta, $qtiTestDefinitionUri, $qtiTestCompilationUri, $standalone, $compilationDirs);
             } else {
                 common_Logger::i('Try to use an extra context builder class that is not an instance of \\oat\\taoQtiTest\\models\\TestContextBuilder!');
             }
         }
     }
     return $context;
 }