Exemplo n.º 1
0
 /**
  * Test update question flag
  */
 public function test_core_question_update_flag()
 {
     $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
     // Create a question category.
     $cat = $questiongenerator->create_question_category();
     $quba = question_engine::make_questions_usage_by_activity('core_question_update_flag', context_system::instance());
     $quba->set_preferred_behaviour('deferredfeedback');
     $questiondata = $questiongenerator->create_question('numerical', null, array('category' => $cat->id));
     $question = question_bank::load_question($questiondata->id);
     $slot = $quba->add_question($question);
     $qa = $quba->get_question_attempt($slot);
     self::setUser($this->student);
     $quba->start_all_questions();
     question_engine::save_questions_usage_by_activity($quba);
     $qubaid = $quba->get_id();
     $questionid = $question->id;
     $qaid = $qa->get_database_id();
     $checksum = md5($qubaid . "_" . $this->student->secret . "_" . $questionid . "_" . $qaid . "_" . $slot);
     $flag = core_question_external::update_flag($qubaid, $questionid, $qaid, $slot, $checksum, true);
     $this->assertTrue($flag['status']);
     // Test invalid checksum.
     try {
         // Using random_string to force failing.
         $checksum = md5($qubaid . "_" . random_string(11) . "_" . $questionid . "_" . $qaid . "_" . $slot);
         core_question_external::update_flag($qubaid, $questionid, $qaid, $slot, $checksum, true);
         $this->fail('Exception expected due to invalid checksum.');
     } catch (moodle_exception $e) {
         $this->assertEquals('errorsavingflags', $e->errorcode);
     }
 }
 public function test_second_attempt_uses_other_dataset()
 {
     global $DB;
     $this->resetAfterTest();
     $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
     $cat = $generator->create_question_category();
     $questiondata = $generator->create_question('calculated', null, array('category' => $cat->id));
     // Create two dataset items.
     $adefinitionid = $DB->get_field_sql("\n                    SELECT qdd.id\n                      FROM {question_dataset_definitions} qdd\n                      JOIN {question_datasets} qd ON qd.datasetdefinition = qdd.id\n                     WHERE qd.question = ?\n                       AND qdd.name = ?", array($questiondata->id, 'a'));
     $bdefinitionid = $DB->get_field_sql("\n                    SELECT qdd.id\n                      FROM {question_dataset_definitions} qdd\n                      JOIN {question_datasets} qd ON qd.datasetdefinition = qdd.id\n                     WHERE qd.question = ?\n                       AND qdd.name = ?", array($questiondata->id, 'b'));
     $DB->set_field('question_dataset_definitions', 'itemcount', 2, array('id' => $adefinitionid));
     $DB->set_field('question_dataset_definitions', 'itemcount', 2, array('id' => $bdefinitionid));
     $DB->insert_record('question_dataset_items', array('definition' => $adefinitionid, 'itemnumber' => 1, 'value' => 3));
     $DB->insert_record('question_dataset_items', array('definition' => $bdefinitionid, 'itemnumber' => 1, 'value' => 7));
     $DB->insert_record('question_dataset_items', array('definition' => $adefinitionid, 'itemnumber' => 2, 'value' => 6));
     $DB->insert_record('question_dataset_items', array('definition' => $bdefinitionid, 'itemnumber' => 2, 'value' => 4));
     $question = question_bank::load_question($questiondata->id);
     $quba1 = question_engine::make_questions_usage_by_activity('test', context_system::instance());
     $quba1->set_preferred_behaviour('deferredfeedback');
     $slot1 = $quba1->add_question($question);
     $quba1->start_all_questions(new core_question\engine\variants\least_used_strategy($quba1, new qubaid_list(array())));
     question_engine::save_questions_usage_by_activity($quba1);
     $variant1 = $quba1->get_variant($slot1);
     // Second attempt should use the other variant.
     $quba2 = question_engine::make_questions_usage_by_activity('test', context_system::instance());
     $quba2->set_preferred_behaviour('deferredfeedback');
     $slot2 = $quba2->add_question($question);
     $quba2->start_all_questions(new core_question\engine\variants\least_used_strategy($quba1, new qubaid_list(array($quba1->get_id()))));
     question_engine::save_questions_usage_by_activity($quba2);
     $variant2 = $quba2->get_variant($slot2);
     $this->assertNotEquals($variant1, $variant2);
     // Third attempt uses either variant at random.
     $quba3 = question_engine::make_questions_usage_by_activity('test', context_system::instance());
     $quba3->set_preferred_behaviour('deferredfeedback');
     $slot3 = $quba3->add_question($question);
     $quba3->start_all_questions(new core_question\engine\variants\least_used_strategy($quba1, new qubaid_list(array($quba1->get_id(), $quba2->get_id()))));
     $variant3 = $quba3->get_variant($slot3);
     $this->assertTrue($variant3 == $variant1 || $variant3 == $variant2);
 }
Exemplo n.º 3
0
 /**
  * Regrade a particular quiz attempt. Either for real ($dryrun = false), or
  * as a pretend regrade to see which fractions would change. The outcome is
  * stored in the quiz_overview_regrades table.
  *
  * Note, $attempt is not upgraded in the database. The caller needs to do that.
  * However, $attempt->sumgrades is updated, if this is not a dry run.
  *
  * @param object $attempt the quiz attempt to regrade.
  * @param bool $dryrun if true, do a pretend regrade, otherwise do it for real.
  * @param array $slots if null, regrade all questions, otherwise, just regrade
  *      the quetsions with those slots.
  */
 protected function regrade_attempt($attempt, $dryrun = false, $slots = null)
 {
     global $DB;
     // Need more time for a quiz with many questions.
     set_time_limit(300);
     $transaction = $DB->start_delegated_transaction();
     $quba = question_engine::load_questions_usage_by_activity($attempt->uniqueid);
     if (is_null($slots)) {
         $slots = $quba->get_slots();
     }
     $finished = $attempt->state == quiz_attempt::FINISHED;
     foreach ($slots as $slot) {
         $qqr = new stdClass();
         $qqr->oldfraction = $quba->get_question_fraction($slot);
         $quba->regrade_question($slot, $finished);
         $qqr->newfraction = $quba->get_question_fraction($slot);
         if (abs($qqr->oldfraction - $qqr->newfraction) > 1.0E-7) {
             $qqr->questionusageid = $quba->get_id();
             $qqr->slot = $slot;
             $qqr->regraded = empty($dryrun);
             $qqr->timemodified = time();
             $DB->insert_record('quiz_overview_regrades', $qqr, false);
         }
     }
     if (!$dryrun) {
         question_engine::save_questions_usage_by_activity($quba);
     }
     $transaction->allow_commit();
     // Really, PHP should not need this hint, but without this, we just run out of memory.
     $quba = null;
     $transaction = null;
     gc_collect_cycles();
 }
 /**
  * Makes an attempt for one student in this quiz, answering all the questions.
  *
  * @param $student
  * @param $quiz
  * @return int How many questions answers were made.
  */
 public function make_student_quiz_atttempt($student, $quiz)
 {
     $submissioncount = 0;
     $attempt = $this->start_quiz_attempt($quiz->id, $student->id);
     $quba = question_engine::load_questions_usage_by_activity($attempt->uniqueid);
     // This bit strips out bits of quiz_attempt::process_submitted_actions()
     // Simulates data from the form.
     // TODO iterate over the questions.
     $formdata = array('answer' => 'Sample essay answer text', 'answerformat' => FORMAT_MOODLE);
     $slot = 1;
     // Only 1 question so far.
     $quba->process_action($slot, $formdata, time());
     $submissioncount++;
     question_engine::save_questions_usage_by_activity($quba);
     $this->end_quiz_attmept($attempt);
     return $submissioncount;
 }
Exemplo n.º 5
0
/**
 * The save started question usage and quiz attempt in db and log the started attempt.
 *
 * @param quiz                       $quizobj
 * @param question_usage_by_activity $quba
 * @param object                     $attempt
 * @return object                    attempt object with uniqueid and id set.
 */
function quiz_attempt_save_started($quizobj, $quba, $attempt)
{
    global $DB;
    // Save the attempt in the database.
    question_engine::save_questions_usage_by_activity($quba);
    $attempt->uniqueid = $quba->get_id();
    $attempt->id = $DB->insert_record('quiz_attempts', $attempt);
    // Params used by the events below.
    $params = array('objectid' => $attempt->id, 'relateduserid' => $attempt->userid, 'courseid' => $quizobj->get_courseid(), 'context' => $quizobj->get_context());
    // Decide which event we are using.
    if ($attempt->preview) {
        $params['other'] = array('quizid' => $quizobj->get_quizid());
        $event = \mod_quiz\event\attempt_preview_started::create($params);
    } else {
        $event = \mod_quiz\event\attempt_started::create($params);
    }
    // Trigger the event.
    $event->add_record_snapshot('quiz', $quizobj->get_quiz());
    $event->add_record_snapshot('quiz_attempts', $attempt);
    $event->trigger();
    return $attempt;
}
Exemplo n.º 6
0
 public function finish_attempt($timestamp)
 {
     global $DB, $USER;
     $this->quba->process_all_actions($timestamp);
     $this->quba->finish_all_questions($timestamp);
     question_engine::save_questions_usage_by_activity($this->quba);
     $this->attempt->timemodified = $timestamp;
     $this->attempt->timefinish = $timestamp;
     $this->attempt->sumgrades = $this->quba->get_total_mark();
     $this->attempt->persent = round((double) $this->quba->get_total_mark() / (double) $this->readerobj->quiz->sumgrades * 100);
     if ((int) $this->readerobj->reader->percentforreading <= (int) $this->attempt->persent) {
         $this->attempt->passed = 'true';
         $passedlog = "Passed";
     } else {
         $this->attempt->passed = 'false';
         $passedlog = "Failed";
     }
     //add_to_log($this->readerobj->course->id, "reader", "finish attempt: ".addslashes($this->readerobj->book->name), "view.php?id={$this->readerobj->reader->id}", $this->attempt->persent."%/".$this->attempt->passed);
     add_to_log($this->readerobj->course->id, "reader", "view attempt: " . addslashes($this->readerobj->book->name), "view.php?id={$this->attempt->id}", "readerID {$this->readerobj->reader->id}; reader quiz {$this->readerobj->book->id}; {$this->attempt->persent}/{$passedlog}");
     $DB->update_record('reader_attempts', $this->attempt);
 }
Exemplo n.º 7
0
 public function process_finish($timestamp, $processsubmitted)
 {
     global $DB;
     $transaction = $DB->start_delegated_transaction();
     if ($processsubmitted) {
         $this->quba->process_all_actions($timestamp);
     }
     $this->quba->finish_all_questions($timestamp);
     question_engine::save_questions_usage_by_activity($this->quba);
     $this->attempt->timemodified = $timestamp;
     $this->attempt->timefinish = $timestamp;
     $this->attempt->sumgrades = $this->quba->get_total_mark();
     $this->attempt->state = self::FINISHED;
     $this->attempt->timecheckstate = null;
     $DB->update_record('quiz_attempts', $this->attempt);
     if (!$this->is_preview()) {
         quiz_save_best_grade($this->get_quiz(), $this->attempt->userid);
         // Trigger event.
         $this->fire_state_transition_event('\\mod_quiz\\event\\attempt_submitted', $timestamp);
         // Tell any access rules that care that the attempt is over.
         $this->get_access_manager($timestamp)->current_attempt_finished();
     }
     $transaction->allow_commit();
 }
Exemplo n.º 8
0
        $oldnumberstonew[$oldslot] = $newslot;
    }
    // Update attempt layout.
    $newlayout = array();
    foreach (explode(',', $lastattempt->layout) as $oldslot) {
        if ($oldslot != 0) {
            $newlayout[] = $oldnumberstonew[$oldslot];
        } else {
            $newlayout[] = 0;
        }
    }
    $attempt->layout = implode(',', $newlayout);
}
// Save the attempt in the database.
$transaction = $DB->start_delegated_transaction();
question_engine::save_questions_usage_by_activity($quba);
$attempt->uniqueid = $quba->get_id();
$attempt->id = $DB->insert_record('quiz_attempts', $attempt);
// Log the new attempt.
if ($attempt->preview) {
    add_to_log($course->id, 'quiz', 'preview', 'view.php?id=' . $quizobj->get_cmid(), $quizobj->get_quizid(), $quizobj->get_cmid());
} else {
    add_to_log($course->id, 'quiz', 'attempt', 'review.php?attempt=' . $attempt->id, $quizobj->get_quizid(), $quizobj->get_cmid());
}
// Trigger event.
$eventdata = new stdClass();
$eventdata->component = 'mod_quiz';
$eventdata->attemptid = $attempt->id;
$eventdata->timestart = $attempt->timestart;
$eventdata->timestamp = $attempt->timestart;
$eventdata->userid = $attempt->userid;
 /**
  * saves the current attempt class
  *
  * @return bool
  */
 public function save()
 {
     global $DB;
     // first save the question usage by activity object
     \question_engine::save_questions_usage_by_activity($this->quba);
     // add the quba id as the questionengid
     // this is here because for new usages there is no id until we save it
     $this->attempt->questionengid = $this->quba->get_id();
     $this->attempt->timemodified = time();
     if (isset($this->attempt->id)) {
         // update the record
         try {
             $DB->update_record('activequiz_attempts', $this->attempt);
         } catch (\Exception $e) {
             error_log($e->getMessage());
             return false;
             // return false on failure
         }
     } else {
         // insert new record
         try {
             $newid = $DB->insert_record('activequiz_attempts', $this->attempt);
             $this->attempt->id = $newid;
         } catch (\Exception $e) {
             return false;
             // return false on failure
         }
     }
     return true;
     // return true if we get here
 }
Exemplo n.º 10
0
 public function test_previously_used_question_not_returned_until_later()
 {
     $this->resetAfterTest();
     $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
     $cat = $generator->create_question_category();
     $question1 = $generator->create_question('shortanswer', null, array('category' => $cat->id));
     $question2 = $generator->create_question('shortanswer', null, array('category' => $cat->id));
     $quba = question_engine::make_questions_usage_by_activity('test', context_system::instance());
     $quba->set_preferred_behaviour('deferredfeedback');
     $question = question_bank::load_question($question2->id);
     $quba->add_question($question);
     $quba->add_question($question);
     $quba->start_all_questions();
     question_engine::save_questions_usage_by_activity($quba);
     $loader = new \core_question\bank\random_question_loader(new qubaid_list(array($quba->get_id())));
     $this->assertEquals($question1->id, $loader->get_next_question_id($cat->id, 0));
     $this->assertEquals($question2->id, $loader->get_next_question_id($cat->id, 0));
     $this->assertNull($loader->get_next_question_id($cat->id, 0));
 }
Exemplo n.º 11
0
 public function get_clone($qinstances)
 {
     // The new quba doesn't have to be cloned, so we can use the parent class.
     $newquba = question_engine::make_questions_usage_by_activity($this->owningcomponent, $this->context);
     $newquba->set_preferred_behaviour('immediatefeedback');
     foreach ($this->get_slots() as $slot) {
         $slotquestion = $this->get_question($slot);
         $attempt = $this->get_question_attempt($slot);
         // We have to check for the type because we might have old migrated templates
         // that could contain description questions.
         if ($slotquestion->get_type_name() == 'multichoice' || $slotquestion->get_type_name() == 'multichoiceset') {
             $order = $slotquestion->get_order($attempt);
             // Order of the answers.
             $order = implode(',', $order);
             $newslot = $newquba->add_question($slotquestion, $qinstances[$slotquestion->id]->maxmark);
             $qa = $newquba->get_question_attempt($newslot);
             $qa->start('immediatefeedback', 1, array('_order' => $order));
         }
     }
     question_engine::save_questions_usage_by_activity($newquba);
     return $newquba;
 }
Exemplo n.º 12
0
/**
 * Checks whether a given result is complete, i.e. all contributing scanned pages have been submitted.
 * Updates the result in the DB if it is complete. Also updates the scanned pages that were duplicates from
 * 'doublepage' to 'resultexists'
 *
 * @param object $offlinequiz
 * @param object $group
 * @param object $result
 * @return boolean
 */
function offlinequiz_check_result_completed($offlinequiz, $group, $result)
{
    global $DB;
    $resultpages = $DB->get_records_sql("SELECT *\n               FROM {offlinequiz_scanned_pages}\n              WHERE resultid = :resultid\n                AND status = 'submitted'", array('resultid' => $result->id));
    if (count($resultpages) == $group->numberofpages) {
        $transaction = $DB->start_delegated_transaction();
        $quba = question_engine::load_questions_usage_by_activity($result->usageid);
        $quba->finish_all_questions(time());
        $totalmark = $quba->get_total_mark();
        question_engine::save_questions_usage_by_activity($quba);
        $result->sumgrades = $totalmark;
        $result->status = 'complete';
        $result->timestart = time();
        $result->timefinish = time();
        $result->timemodified = time();
        $DB->update_record('offlinequiz_results', $result);
        $transaction->allow_commit();
        offlinequiz_update_grades($offlinequiz, $result->userid);
        // Change the error of all submitted pages of the result to '' (was 'missingpages' before).
        foreach ($resultpages as $page) {
            $DB->set_field('offlinequiz_scanned_pages', 'error', '', array('id' => $page->id));
        }
        // Change the status of all double pages of the user to 'resultexists'.
        $offlinequizconfig = get_config('offlinequiz');
        $user = $DB->get_record('user', array('id' => $result->userid));
        $sql = "SELECT id\n                  FROM {offlinequiz_scanned_pages}\n                 WHERE offlinequizid = :offlinequizid\n                   AND userkey = :userkey\n                   AND groupnumber = :groupnumber\n                   AND error = 'doublepage'";
        $params = array('offlinequizid' => $offlinequiz->id, 'userkey' => $user->{$offlinequizconfig->ID_field}, 'groupnumber' => $group->number);
        $doublepages = $DB->get_records_sql($sql, $params);
        foreach ($doublepages as $page) {
            $DB->set_field('offlinequiz_scanned_pages', 'error', 'resultexists', array('id' => $page->id));
            $DB->set_field('offlinequiz_scanned_pages', 'resultid', 0, array('id' => $page->id));
        }
        return true;
    }
    return false;
}
Exemplo n.º 13
0
 private static function quiz_attempt_process($id, $step, $forcenew, $page, $uid, $request, $key, $startedOn)
 {
     global $DB, $USER;
     $USER->id = $uid;
     $response = new CliniqueServiceResponce();
     $quizobj = '';
     //$timenow = time(); // Update time now, in case the server is running really slowly.
     $timenow = $startedOn;
     if (!($cm = get_coursemodule_from_id('quiz', $id))) {
         print_error('invalidcoursemodule');
     }
     $quizobj = quiz::create($cm->instance, $uid);
     $attempts_allowed = self::attempts_allowed($attempt, $quizobj);
     // Create an object to manage all the other (non-roles) access rules.
     $accessmanager = $quizobj->get_access_manager($timenow);
     $attempt_nums = self::accessmanager_process($quizobj, $accessmanager, $forcenew, $uid);
     if ($attempts_allowed != 0) {
         if ($attempts_allowed < $attempt_nums->attemptnumber) {
             $block_res = self::get_blocked_response($request, '', $key);
             $response->response(false, "", $block_res);
             die;
             // $response->response(false, "", $request);
         }
     }
     $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context());
     $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour);
     // Create the new attempt and initialize the question sessions
     $attempt = quiz_create_attempt($quizobj, $attempt_nums->attemptnumber, $attempt_nums->lastattempt, $timenow, $quizobj->is_preview_user());
     self::quiz_attempt_stepone($attempt, $attempt_nums->lastattempt, $quizobj, $timenow, $quba, $attempt_nums->attemptnumber);
     // Save the attempt in the database.
     $transaction = $DB->start_delegated_transaction();
     question_engine::save_questions_usage_by_activity($quba);
     $attempt->uniqueid = $quba->get_id();
     $attempt->id = $DB->insert_record('quiz_attempts', $attempt);
     // Trigger event.
     $res = self::trigger_event($attempt, $quizobj);
     $transaction->allow_commit();
     return $res;
 }
Exemplo n.º 14
0
/**
 * The save started question usage and quiz attempt in db and log the started attempt.
 *
 * @param quiz                       $quizobj
 * @param question_usage_by_activity $quba
 * @param object                     $attempt
 * @return object                    attempt object with uniqueid and id set.
 */
function quiz_attempt_save_started($quizobj, $quba, $attempt) {
    global $DB;
    // Save the attempt in the database.
    question_engine::save_questions_usage_by_activity($quba);
    $attempt->uniqueid = $quba->get_id();
    $attempt->id = $DB->insert_record('quiz_attempts', $attempt);
    // Log the new attempt.
    if ($attempt->preview) {
        add_to_log($quizobj->get_courseid(), 'quiz', 'preview', 'view.php?id='.$quizobj->get_cmid(),
                   $quizobj->get_quizid(), $quizobj->get_cmid());
    } else {
        add_to_log($quizobj->get_courseid(), 'quiz', 'attempt', 'review.php?attempt='.$attempt->id,
                   $quizobj->get_quizid(), $quizobj->get_cmid());
    }
    return $attempt;
}
Exemplo n.º 15
0
 /**
  * Regrade a particular offlinequiz result. Either for real ($dryrun = false), or
  * as a pretend regrade to see which fractions would change. The outcome is
  * stored in the offlinequiz_overview_regrades table.
  *
  * Note, $result is not upgraded in the database. The caller needs to do that.
  * However, $result->sumgrades is updated, if this is not a dry run.
  *
  * @param object $result the offlinequiz result to regrade.
  * @param bool $dryrun if true, do a pretend regrade, otherwise do it for real.
  * @param array $slots if null, regrade all questions, otherwise, just regrade
  *      the quetsions with those slots.
  */
 protected function regrade_result($result, $questions, $dryrun = false, $slots = null)
 {
     global $DB;
     $transaction = $DB->start_delegated_transaction();
     $quba = question_engine::load_questions_usage_by_activity($result->usageid);
     if (is_null($slots)) {
         $slots = $quba->get_slots();
     }
     $changed = false;
     $finished = true;
     foreach ($slots as $slot) {
         $qqr = new stdClass();
         $qqr->oldfraction = $quba->get_question_fraction($slot);
         $slotquestion = $quba->get_question($slot);
         $newmaxmark = $questions[$slotquestion->id]->maxmark;
         $quba->regrade_question($slot, $finished, $newmaxmark);
         $qqr->newfraction = $quba->get_question_fraction($slot);
         if (abs($qqr->oldfraction - $qqr->newfraction) > 1.0E-7) {
             $changed = true;
         }
     }
     if (!$dryrun) {
         question_engine::save_questions_usage_by_activity($quba);
     }
     $transaction->allow_commit();
     return $changed;
 }
Exemplo n.º 16
0
 protected function save_quba(moodle_database $db = null)
 {
     question_engine::save_questions_usage_by_activity($this->quba, $db);
 }
 /**
  * Creates a single printable copy of the given quiz.
  *
  * @return  The ID of the created printable question usage.
  *
  */
 protected function create_printable_copy($shuffle_mode = quiz_papercopy_shuffle_modes::MODE_SHUFFLE_IGNORE_PAGES, $fix_descriptions = false, $fix_first = false, $fix_last = false)
 {
     //get a reference to the current user
     global $USER;
     //create a new usage object, which will allow us to create a psuedoquiz in the same context as the online quiz
     $usage = question_engine::make_questions_usage_by_activity('mod_quiz', $this->context);
     //and set the grading mode to "deferred feedback", the standard for paper quizzes
     //this makes sense, since our paradigm is duriven by the idea that feedback is only offered once a paper quiz has been uploaded/graded
     $usage->set_preferred_behaviour('deferredfeedback');
     //get an array of questions in the current quiz
     $quiz_questions = $this->quizobj->get_questions();
     //randomize the question order, as requested
     $quiz_questions = self::shuffle_questions($quiz_questions, $this->quiz->questions, $shuffle_mode, $fix_descriptions, $fix_first, $fix_last);
     //for each question in our online quiz
     foreach ($quiz_questions as $slot => $qdata) {
         $question = question_bank::make_question($qdata);
         //add the new question instance to our new printable copy, keeping the maximum grade from the quiz
         //TODO: respect maximum marks
         $usage->add_question($question);
     }
     //initialize each of the questions
     $usage->start_all_questions();
     //save the usage to the database
     question_engine::save_questions_usage_by_activity($usage);
     //return the ID of the newly created questions usage
     return $usage->get_id();
 }
Exemplo n.º 18
0
 public function test_load_used_variants()
 {
     $this->resetAfterTest();
     $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
     $cat = $generator->create_question_category();
     $questiondata1 = $generator->create_question('shortanswer', null, array('category' => $cat->id));
     $questiondata2 = $generator->create_question('shortanswer', null, array('category' => $cat->id));
     $questiondata3 = $generator->create_question('shortanswer', null, array('category' => $cat->id));
     $quba = question_engine::make_questions_usage_by_activity('test', context_system::instance());
     $quba->set_preferred_behaviour('deferredfeedback');
     $question1 = question_bank::load_question($questiondata1->id);
     $question3 = question_bank::load_question($questiondata3->id);
     $quba->add_question($question1);
     $quba->add_question($question1);
     $quba->add_question($question3);
     $quba->start_all_questions();
     question_engine::save_questions_usage_by_activity($quba);
     $this->assertEquals(array($questiondata1->id => array(1 => 2), $questiondata2->id => array(), $questiondata3->id => array(1 => 1)), question_engine::load_used_variants(array($questiondata1->id, $questiondata2->id, $questiondata3->id), new qubaid_list(array($quba->get_id()))));
 }
 public function finish_attempt($timestamp)
 {
     global $DB, $USER;
     $this->quba->process_all_actions($timestamp);
     $this->quba->finish_all_questions($timestamp);
     question_engine::save_questions_usage_by_activity($this->quba);
     $this->attempt->timemodified = $timestamp;
     $this->attempt->timefinish = $timestamp;
     $this->attempt->sumgrades = $this->quba->get_total_mark();
     $DB->update_record('quiz_attempts', $this->attempt);
     if (!$this->is_preview()) {
         quiz_save_best_grade($this->get_quiz());
         // Trigger event
         $eventdata = new stdClass();
         $eventdata->component = 'mod_quiz';
         $eventdata->attemptid = $this->attempt->id;
         $eventdata->timefinish = $this->attempt->timefinish;
         $eventdata->userid = $this->attempt->userid;
         $eventdata->submitterid = $USER->id;
         $eventdata->quizid = $this->get_quizid();
         $eventdata->cmid = $this->get_cmid();
         $eventdata->courseid = $this->get_courseid();
         events_trigger('quiz_attempt_submitted', $eventdata);
         // Clear the password check flag in the session.
         $this->get_access_manager($timestamp)->clear_password_access();
     }
 }
Exemplo n.º 20
0
 /**
  * Regrade a particular quiz attempt. Either for real ($dryrun = false), or
  * as a pretend regrade to see which fractions would change. The outcome is
  * stored in the quiz_overview_regrades table.
  *
  * Note, $attempt is not upgraded in the database. The caller needs to do that.
  * However, $attempt->sumgrades is updated, if this is not a dry run.
  *
  * @param object $attempt the quiz attempt to regrade.
  * @param bool $dryrun if true, do a pretend regrade, otherwise do it for real.
  * @param array $slots if null, regrade all questions, otherwise, just regrade
  *      the quetsions with those slots.
  */
 protected function regrade_attempt($attempt, $dryrun = false, $slots = null)
 {
     global $DB;
     $transaction = $DB->start_delegated_transaction();
     $quba = question_engine::load_questions_usage_by_activity($attempt->uniqueid);
     if (is_null($slots)) {
         $slots = $quba->get_slots();
     }
     $finished = $attempt->timefinish > 0;
     foreach ($slots as $slot) {
         $qqr = new stdClass();
         $qqr->oldfraction = $quba->get_question_fraction($slot);
         $quba->regrade_question($slot, $finished);
         $qqr->newfraction = $quba->get_question_fraction($slot);
         if (abs($qqr->oldfraction - $qqr->newfraction) > 1.0E-7) {
             $qqr->questionusageid = $quba->get_id();
             $qqr->slot = $slot;
             $qqr->regraded = empty($dryrun);
             $qqr->timemodified = time();
             $DB->insert_record('quiz_overview_regrades', $qqr, false);
         }
     }
     if (!$dryrun) {
         question_engine::save_questions_usage_by_activity($quba);
     }
     $transaction->allow_commit();
 }
Exemplo n.º 21
0
    public function finish_attempt($timestamp) {
        global $DB;
        $this->quba->process_all_actions($timestamp);
        $this->quba->finish_all_questions($timestamp);

        question_engine::save_questions_usage_by_activity($this->quba);

        $this->attempt->timemodified = $timestamp;
        $this->attempt->timefinish = $timestamp;
        $this->attempt->sumgrades = $this->quba->get_total_mark();
        $DB->update_record('quiz_attempts', $this->attempt);

        if (!$this->is_preview()) {
            quiz_save_best_grade($this->get_quiz());
            $this->quiz_send_notification_emails();
        }
    }