public function process_action(question_attempt_pending_step $pendingstep)
 {
     if ($pendingstep->has_behaviour_var('helpme')) {
         return $this->process_helpme($pendingstep);
     } else {
         return parent::process_action($pendingstep);
     }
 }
Beispiel #2
0
 public function process_finish(question_attempt_pending_step $pendingstep)
 {
     if ($this->qa->get_state()->is_finished()) {
         return question_attempt::DISCARD;
     }
     $response = $this->qa->get_last_step()->get_qt_data();
     if (!$this->question->is_complete_response($response)) {
         $pendingstep->set_state(question_state::$gaveup);
     } else {
         $pendingstep->set_state(question_state::$needsgrading);
     }
     $pendingstep->set_new_response_summary($this->question->summarise_response($response));
     return question_attempt::KEEP;
 }
Beispiel #3
0
 protected function adjust_fraction($fraction, question_attempt_pending_step $pendingstep)
 {
     $totaltries = $this->qa->get_step(0)->get_behaviour_var('_triesleft');
     $responses = array();
     $lastsave = array();
     foreach ($this->qa->get_step_iterator() as $step) {
         if ($step->has_behaviour_var('submit') && $step->get_state() != question_state::$invalid) {
             $responses[] = $step->get_qt_data();
             $lastsave = array();
         } else {
             $lastsave = $step->get_qt_data();
         }
     }
     $lastresponse = $pendingstep->get_qt_data();
     if (!empty($lastresponse)) {
         $responses[] = $lastresponse;
     } else {
         if (!empty($lastsave)) {
             $responses[] = $lastsave;
         }
     }
     return $this->question->compute_final_grade($responses, $totaltries);
 }
Beispiel #4
0
 public function process_seen(question_attempt_pending_step $pendingstep)
 {
     $pendingstep->set_state(question_state::$complete);
     return question_attempt::KEEP;
 }
Beispiel #5
0
 public function process_finish(question_attempt_pending_step $pendingstep)
 {
     if ($this->qa->get_state()->is_finished()) {
         return question_attempt::DISCARD;
     }
     $prevtries = $this->qa->get_last_behaviour_var('_try', 0);
     $prevbest = $this->qa->get_fraction();
     if (is_null($prevbest)) {
         $prevbest = 0;
     }
     $laststep = $this->qa->get_last_step();
     $response = $laststep->get_qt_data();
     if (!$this->question->is_gradable_response($response)) {
         $state = question_state::$gaveup;
         $fraction = 0;
     } else {
         if ($laststep->has_behaviour_var('_try')) {
             // Last answer was graded, we want to regrade it. Otherwise the answer
             // has changed, and we are grading a new try.
             $prevtries -= 1;
         }
         list($fraction, $state) = $this->question->grade_response($response);
         $pendingstep->set_behaviour_var('_try', $prevtries + 1);
         $pendingstep->set_behaviour_var('_rawfraction', $fraction);
         $pendingstep->set_new_response_summary($this->question->summarise_response($response));
     }
     $pendingstep->set_state($state);
     $pendingstep->set_fraction(max($prevbest, $this->adjusted_fraction($fraction, $prevtries)));
     return question_attempt::KEEP;
 }
 protected function process_parts_that_can_be_graded(question_attempt_pending_step $pendingstep, $finalsubmit)
 {
     // Get the response we are processing.
     if ($finalsubmit) {
         $laststep = $this->qa->get_last_step();
         $response = $laststep->get_qt_data();
     } else {
         $response = $pendingstep->get_qt_data();
     }
     // Get last graded response for each part.
     $lastgradedresponses = array();
     $currenttries = array();
     $currentpenalties = array();
     $currentfractions = array();
     $currentrawfractions = array();
     $prevseenresponse = array();
     $steps = $this->qa->get_reverse_step_iterator();
     if ($finalsubmit) {
         $steps->next();
     }
     foreach ($steps as $step) {
         foreach ($step->get_behaviour_data() as $name => $value) {
             if (!preg_match('~_tries_(.*)$~', $name, $matches)) {
                 continue;
             }
             $oldresponse = $step->get_qt_data();
             $partname = $matches[1];
             if (array_key_exists($partname, $currenttries)) {
                 // We already have a most recent try for this part, but now
                 // have an older response that was a try for this part, and
                 // we want to know if the current response is the same as this.
                 if ($this->question->is_same_response_for_part($partname, $oldresponse, $response)) {
                     $prevseenresponse[$partname] = true;
                 }
                 continue;
             }
             $lastgradedresponses[$partname] = $oldresponse;
             $currenttries[$partname] = $value;
             $currentpenalties[$partname] = $step->get_behaviour_var('_penalty_' . $partname);
             $currentfractions[$partname] = $step->get_behaviour_var('_fraction_' . $partname);
             $currentrawfractions[$partname] = $step->get_behaviour_var('_rawfraction_' . $partname);
         }
     }
     $partscores = $this->question->grade_parts_that_can_be_graded($response, $lastgradedresponses, $finalsubmit);
     foreach ($partscores as $partname => $partscore) {
         if ($partscore->errors) {
             $pendingstep->set_behaviour_var('_errors_' . $partname, 1);
             continue;
         }
         if (!array_key_exists($partname, $currentpenalties)) {
             $currenttries[$partname] = 0;
             $currentpenalties[$partname] = 0;
             $currentfractions[$partname] = 0;
         }
         if (!empty($prevseenresponse[$partname])) {
             $partscore->penalty = 0;
         }
         $pendingstep->set_behaviour_var('_tries_' . $partname, $currenttries[$partname] + 1);
         if ($this->applypenalties) {
             $pendingstep->set_behaviour_var('_curpenalty_' . $partname, $partscore->penalty);
             $pendingstep->set_behaviour_var('_penalty_' . $partname, min($currentpenalties[$partname] + $partscore->penalty, 1));
             // Cap cumulative penalty at 1.
         } else {
             $pendingstep->set_behaviour_var('_penalty_' . $partname, 0);
         }
         $pendingstep->set_behaviour_var('_rawfraction_' . $partname, $partscore->rawfraction);
         $currentrawfractions[$partname] = $partscore->rawfraction;
         $currentfractions[$partname] = max($partscore->rawfraction - $currentpenalties[$partname], $currentfractions[$partname]);
         // Current fraction never decreases.
         $pendingstep->set_behaviour_var('_fraction_' . $partname, $currentfractions[$partname]);
     }
     if (empty($currentfractions)) {
         $totalfraction = null;
         $overallstate = question_state::$gaveup;
     } else {
         $totalweight = 0;
         $totalfraction = 0;
         foreach ($this->question->get_parts_and_weights() as $index => $weight) {
             $totalweight += $weight;
             if (array_key_exists($index, $currentfractions)) {
                 $totalfraction += $weight * $currentfractions[$index];
             }
         }
         $totalfraction = $totalfraction / $totalweight;
         $allright = true;
         $allwrong = true;
         foreach ($this->question->get_parts_and_weights() as $index => $weight) {
             if (array_key_exists($index, $currentrawfractions)) {
                 $partstate = question_state::graded_state_for_fraction($currentrawfractions[$index]);
                 if ($partstate != question_state::$gradedright) {
                     $allright = false;
                 }
                 if ($partstate != question_state::$gradedwrong) {
                     $allwrong = false;
                 }
             } else {
                 $allright = false;
             }
         }
         if ($allright) {
             $overallstate = question_state::$gradedright;
         } else {
             if ($allwrong) {
                 $overallstate = question_state::$gradedwrong;
             } else {
                 $overallstate = question_state::$gradedpartial;
             }
         }
     }
     return array($totalfraction, $overallstate);
 }
Beispiel #7
0
 public function process_finish(question_attempt_pending_step $pendingstep)
 {
     if ($this->qa->get_state()->is_finished()) {
         return question_attempt::DISCARD;
     }
     $response = $this->qa->get_last_step()->get_qt_data();
     if (!$this->question->is_gradable_response($response)) {
         $pendingstep->set_state(question_state::$gaveup);
     } else {
         list($fraction, $state) = $this->question->grade_response($response);
         $pendingstep->set_fraction($fraction);
         $pendingstep->set_state($state);
     }
     $pendingstep->set_new_response_summary($this->question->summarise_response($response));
     return question_attempt::KEEP;
 }
Beispiel #8
0
    protected function do_grading(question_attempt_step $responsesstep,
            question_attempt_pending_step $pendingstep) {
        if (!$this->question->is_gradable_response($responsesstep->get_qt_data())) {
            $pendingstep->set_state(question_state::$gaveup);

        } else {
            $response = $responsesstep->get_qt_data();
            list($fraction, $state) = $this->question->grade_response($response);

            if ($responsesstep->has_behaviour_var('certainty')) {
                $certainty = $responsesstep->get_behaviour_var('certainty');
            } else {
                $certainty = question_cbm::default_certainty();
                $pendingstep->set_behaviour_var('_assumedcertainty', $certainty);
            }

            $pendingstep->set_behaviour_var('_rawfraction', $fraction);
            $pendingstep->set_fraction(question_cbm::adjust_fraction($fraction, $certainty));
            $pendingstep->set_state($state);
            $pendingstep->set_new_response_summary(question_cbm::summary_with_certainty(
                    $this->question->summarise_response($response),
                    $responsesstep->get_behaviour_var('certainty')));
        }
        return question_attempt::KEEP;
    }
Beispiel #9
0
 public function process_finish(question_attempt_pending_step $pendingstep)
 {
     if ($this->qa->get_state()->is_finished()) {
         return question_attempt::DISCARD;
     }
     $prevtries = $this->qa->get_last_behaviour_var('_try', 0);
     $prevbest = $this->qa->get_fraction();
     if (is_null($prevbest)) {
         $prevbest = 0;
     }
     $laststep = $this->qa->get_last_step();
     $response = $laststep->get_qt_data();
     if (!$this->question->is_gradable_response($response)) {
         $state = question_state::$gaveup;
         $fraction = 0;
     } else {
         if ($laststep->has_behaviour_var('_try')) {
             // Last answer was graded, we want to regrade it. Otherwise the answer
             // has changed, and we are grading a new try.
             // There is a Moodle bug here, resulting in regrading of
             // already-graded questions.
             // See https://tracker.moodle.org/browse/MDL-42399
             $prevtries -= 1;
         }
         // *** changed bit #2 begins ***
         // Cache extra data from grade response.
         $gradedata = $this->question->grade_response($response);
         list($fraction, $state) = $gradedata;
         if (count($gradedata) > 2) {
             foreach ($gradedata[2] as $name => $value) {
                 $pendingstep->set_qt_var($name, $value);
             }
         }
         // *** end of changed bit #2 ***
         $pendingstep->set_behaviour_var('_try', $prevtries + 1);
         $pendingstep->set_behaviour_var('_rawfraction', $fraction);
         $pendingstep->set_new_response_summary($this->question->summarise_response($response));
     }
     $pendingstep->set_state($state);
     $pendingstep->set_fraction(max($prevbest, $this->adjusted_fraction($fraction, $prevtries)));
     return question_attempt::KEEP;
 }
 public function process_submit(question_attempt_pending_step $pendingstep)
 {
     // Must find out prevbest before parent function get in it's fraction.
     $prevbest = $pendingstep->get_fraction();
     if (is_null($prevbest)) {
         $prevbest = 0;
     }
     $status = parent::process_submit($pendingstep);
     $response = $pendingstep->get_qt_data();
     if ($this->question->is_gradable_response($response) && $status == question_attempt::KEEP) {
         // State was graded.
         $prevtotal = $this->qa->get_last_behaviour_var('_totalpenalties', 0);
         // The fraction = rawfraction - totalpenalties (already collected).
         $pendingstep->set_fraction(max($prevbest, $this->adjusted_fraction($pendingstep->get_behaviour_var('_rawfraction'), $prevtotal)));
         $pendingstep->set_behaviour_var('_totalpenalties', $prevtotal + $this->question->penalty);
         // For submit penalty is added after fraction is calculated.
         $pendingstep->set_behaviour_var('_penalty', $this->question->penalty);
     }
     return $status;
 }