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); }
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); }
public function process_submit(question_attempt_pending_step $pendingstep) { if ($this->qa->get_state()->is_finished()) { return question_attempt::DISCARD; } if (!$this->qa->get_question()->is_gradable_response($pendingstep->get_qt_data()) || !$pendingstep->has_behaviour_var('certainty')) { $pendingstep->set_state(question_state::$invalid); return question_attempt::KEEP; } return $this->do_grading($pendingstep, $pendingstep); }
public function process_action(question_attempt_pending_step $pendingstep) { $result = null; // Process hint button press. foreach ($this->question->hints_available_for_student($pendingstep->get_qt_data()) as $hintkey) { $hintkey = $this->adjust_hintkey($hintkey); if ($pendingstep->has_behaviour_var($hintkey . 'btn')) { $result = $this->process_hint($pendingstep, $hintkey); } } // Proces all actions. if ($result === null) { $result = parent::process_action($pendingstep); } // Compute variables to show question it should render it's hint buttons. if (!$this->qa->get_state()->is_finished()) { $pendingstep->set_behaviour_var('_nonresp_hintbtns', true); $response = $pendingstep->get_qt_data(); if ($this->question->is_complete_response($response)) { $pendingstep->set_behaviour_var('_resp_hintbtns', true); } } return $result; }
protected function grade_response(question_attempt_pending_step $pendingstep, $isprecheck) { $response = $pendingstep->get_qt_data(); $gradedata = $this->question->grade_response($response, $isprecheck); list($fraction, $state) = $gradedata; if (count($gradedata) > 2) { foreach ($gradedata[2] as $name => $value) { $pendingstep->set_qt_var($name, $value); } } return array($fraction, $state); }