MDL-29483, MDL-29482 advanced grading in assignment, rubrics editor

- advanced grading plugins now return the grade in the specified range
- prohibited quick grading when advanced grading method is used
- fixed bug in processing description in rubric editor
- some improvements to rubric editor JS
This commit is contained in:
Marina Glancy
2011-10-21 13:58:52 +08:00
parent 36937f0264
commit 9e2eca0fde
6 changed files with 93 additions and 40 deletions
+32 -5
View File
@@ -50,6 +50,9 @@ abstract class gradingform_controller {
/** @var stdClass|false the definition structure */
protected $definition;
/** @var array graderange array of valid grades for this area. Use set_grade_range and get_grade_range to access this */
private $graderange = null;
/**
* Do not instantinate this directly, use {@link grading_manager::get_controller()}
*
@@ -174,9 +177,10 @@ abstract class gradingform_controller {
/**
* Returns the grading form definition structure
*
* @param boolean $force whether to force loading from DB even if it was already loaded
* @return stdClass|false definition data or false if the form is not defined yet
*/
public function get_definition() {
public function get_definition($force = false) {
if (is_null($this->definition)) {
$this->load_definition();
}
@@ -459,12 +463,33 @@ abstract class gradingform_controller {
*
* @param moodle_page $page
* @param int $itemid
* @param string $defaultcontent default string to be returned if no active grading is found
* @param array $grading_info result of function grade_get_grades if plugin want to use some of their info
* @param string $defaultcontent default string to be returned if no active grading is found or for some reason can not be shown to a user
* @return string
*/
public function render_grade($page, $itemid, $defaultcontent) {
public function render_grade($page, $itemid, $grading_info, $defaultcontent) {
return $defaultcontent;
}
/**
* Sets the range of grades used in this area. This is usually either range like 0-100
* or the scale where keys start from 1. Typical use:
* $controller->set_grade_range(make_grades_menu($gradingtype));
*/
public final function set_grade_range(array $graderange) {
$this->graderange = $graderange;
}
/**
* Returns the range of grades used in this area
* @return array
*/
public final function get_grade_range() {
if (empty($this->graderange)) {
return array();
}
return $this->graderange;
}
}
/**
@@ -600,7 +625,8 @@ abstract class gradingform_instance {
/**
* Calculates the grade to be pushed to the gradebook
* @return int the grade on 0-100 scale
*
* @return int the valid grade from $this->get_controller()->get_grade_range()
*/
abstract public function get_grade();
@@ -622,11 +648,12 @@ abstract class gradingform_instance {
* If there are more than one input elements they MUST be elements of array with
* name $gradingformelement->getName().
* Example: {NAME}[myelement1], {NAME}[myelement2][sub1], {NAME}[myelement2][sub2], etc.
* ( {NAME} is a shortcut for $gradingformelement->getName() )
* After submitting the form the value of $_POST[{NAME}] is passed to the functions
* validate_grading_element() and submit_and_get_grade()
*
* Plugins may use $gradingformelement->getValue() to get the value passed on previous
* from submit
* form submit
*
* When forming html it is a plugin's responsibility to analyze flags
* $gradingformelement->_flagFrozen and $gradingformelement->_persistantFreeze:
+1 -2
View File
@@ -46,14 +46,13 @@ $PAGE->set_heading(get_string('definerubric', 'gradingform_rubric'));
$PAGE->requires->js('/grade/grading/form/rubric/js/rubriceditor.js');
//TODO freeze rubric editor if needed
$mform = new gradingform_rubric_editrubric(null, array('areaid' => $areaid, 'freezerubric' => optional_param('freeze', 0, PARAM_INT)));
$mform = new gradingform_rubric_editrubric(null, array('areaid' => $areaid, 'context' => $context, 'freezerubric' => optional_param('freeze', 0, PARAM_INT)));
$mform->set_data($controller->get_definition_for_editing());
if ($mform->is_cancelled()) {
// todo process editing cancel in a better way
redirect($manager->get_management_url());
} else if ($data = $mform->get_data()) {
$data = $controller->postupdate_definition_data($data);
$controller->update_definition($data);
redirect($PAGE->url);
}
+1 -1
View File
@@ -50,7 +50,7 @@ class gradingform_rubric_editrubric extends moodleform {
$form->setType('name', PARAM_TEXT);
// description
$options = array();
$options = gradingform_rubric_controller::description_form_field_options($this->_customdata['context']);
$form->addElement('editor', 'description_editor', get_string('description', 'gradingform_rubric'), null, $options);
$form->setType('description_editor', PARAM_RAW);
@@ -83,6 +83,7 @@ M.gradingform_rubriceditor.editmode = function(el, editmode) {
}
ta.get('parentNode').one('.plainvalue').setStyle('display', 'none')
ta.setStyle('display', 'block').setStyle('width', width).setStyle('height', height)
ta.focus()
}
}
+29 -25
View File
@@ -60,19 +60,28 @@ class gradingform_rubric_controller extends gradingform_controller {
* Saves the rubric definition into the database
*
* @see parent::update_definition()
* @param stdClass $newdefinition rubric definition data as coming from {@link self::postupdate_definition_data()}
* @param stdClass $newdefinition rubric definition data as coming from gradingform_rubric_editrubric::get_data()
* @param int|null $usermodified optional userid of the author of the definition, defaults to the current user
*/
public function update_definition(stdClass $newdefinition, $usermodified = null) {
global $DB;
// firstly update the common definition data in the {grading_definition} table
if ($this->definition === false) {
// if definition does not exist yet, create a blank one with only required fields set
// (we need id to save files embedded in description)
parent::update_definition((object)array('descriptionformat' => FORMAT_MOODLE), $usermodified);
parent::load_definition();
}
$options = self::description_form_field_options($this->get_context());
$newdefinition = file_postupdate_standard_editor($newdefinition, 'description', $options, $this->get_context(),
'gradingform_rubric', 'definition_description', $this->definition->id);
parent::update_definition($newdefinition, $usermodified);
// reload the definition from the database
$this->load_definition();
$currentdefinition = $this->get_definition();
// update current data
// reload the definition from the database
$currentdefinition = $this->get_definition(true);
// update rubric data
$haschanges = false;
if (empty($newdefinition->rubric_criteria)) {
$newcriteria = array();
@@ -299,21 +308,6 @@ class gradingform_rubric_controller extends gradingform_controller {
return format_text($description, $this->definition->descriptionformat, $formatoptions);
}
/**
* Converts the rubric definition data from the submitted form back to the form
* suitable for storing in database
*/
public function postupdate_definition_data($data) {
if (!$this->definition) {
return $data;
}
$options = self::description_form_field_options($this->get_context());
$data = file_postupdate_standard_editor($data, 'description', $options, $this->get_context(),
'gradingform_rubric', 'definition_description', $this->definition->id);
// TODO change filearea for embedded files in grading_definition.description
return $data;
}
public function is_form_available($foruserid = null) {
return true;
// TODO this is temporary for testing!
@@ -373,10 +367,11 @@ class gradingform_rubric_controller extends gradingform_controller {
*
* @param moodle_page $page
* @param int $itemid
* @param array $grading_info result of function grade_get_grades
* @param string $defaultcontent default string to be returned if no active grading is found
* @return string
*/
public function render_grade($page, $itemid, $defaultcontent) {
public function render_grade($page, $itemid, $grading_info, $defaultcontent) {
$instances = $this->get_current_instances($itemid);
return $this->get_renderer($page)->display_instances($this->get_current_instances($itemid), $defaultcontent);
}
@@ -484,7 +479,8 @@ class gradingform_rubric_instance extends gradingform_instance {
/**
* Calculates the grade to be pushed to the gradebook
* @return int the grade on 0-100 scale
*
* @return int the valid grade from $this->get_controller()->get_grade_range()
*/
public function get_grade() {
global $DB, $USER;
@@ -494,20 +490,28 @@ class gradingform_rubric_instance extends gradingform_instance {
$maxscore = 0;
foreach ($this->get_controller()->get_definition()->rubric_criteria as $id => $criterion) {
$keys = array_keys($criterion['levels']);
// TODO array_reverse($keys) if levels are sorted DESC
sort($keys);
$minscore += $criterion['levels'][$keys[0]]['score'];
$maxscore += $criterion['levels'][$keys[sizeof($keys)-1]]['score'];
}
if ($maxscore == 0) {
if ($maxscore <= $minscore) {
return -1;
}
$graderange = array_keys($this->get_controller()->get_grade_range());
if (empty($graderange)) {
return -1;
}
sort($graderange);
$mingrade = $graderange[0];
$maxgrade = $graderange[sizeof($graderange) - 1];
$curscore = 0;
foreach ($grade as $id => $levelid) {
$curscore += $this->get_controller()->get_definition()->rubric_criteria[$id]['levels'][$levelid]['score'];
}
return $curscore/$maxscore*100; // TODO mapping
return round(($curscore-$minscore)/($maxscore-$minscore)*($maxgrade-$mingrade), 0) + $mingrade; // TODO mapping
}
/**
+29 -7
View File
@@ -332,7 +332,8 @@ class assignment_base {
echo '<td class="content">';
$grade_str = '<div class="grade">'. get_string("grade").': '.$grade->str_long_grade. '</div>';
if (!empty($submission) && $controller = get_grading_manager($this->context, 'mod_assignment', 'submission')->get_active_controller()) {
echo $controller->render_grade($PAGE, $submission->id, $grade_str);
$controller->set_grade_range(make_grades_menu($this->assignment->grade));
echo $controller->render_grade($PAGE, $submission->id, $item, $grade_str);
} else {
echo $grade_str;
}
@@ -780,6 +781,23 @@ class assignment_base {
}
}
/**
* Checks if grading method allows quickgrade mode. At the moment it is hardcoded
* that advanced grading methods do not allow quickgrade.
*
* Assignment type plugins are not allowed to override this method
*
* @return boolean
*/
public final function quickgrade_mode_allowed() {
global $CFG;
require_once("$CFG->dirroot/grade/grading/lib.php");
if ($controller = get_grading_manager($this->context, 'mod_assignment', 'submission')->get_active_controller()) {
return false;
}
return true;
}
/**
* Helper method updating the listing on the main script from popup using javascript
*
@@ -794,7 +812,7 @@ class assignment_base {
$perpage = get_user_preferences('assignment_perpage', 10);
$quickgrade = get_user_preferences('assignment_quickgrade', 0);
$quickgrade = get_user_preferences('assignment_quickgrade', 0) && $this->quickgrade_mode_allowed();
/// Run some Javascript to try and update the parent page
$output .= '<script type="text/javascript">'."\n<!--\n";
@@ -1138,7 +1156,7 @@ class assignment_base {
* from database
*/
$perpage = get_user_preferences('assignment_perpage', 10);
$quickgrade = get_user_preferences('assignment_quickgrade', 0);
$quickgrade = get_user_preferences('assignment_quickgrade', 0) && $this->quickgrade_mode_allowed();
$filter = get_user_preferences('assignment_filter', 0);
$grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id);
@@ -1367,6 +1385,7 @@ class assignment_base {
/// Calculate user status
$auser->status = ($auser->timemarked > 0) && ($auser->timemarked >= $auser->timemodified);
// TODO add here code if advanced grading grade must be reviewed => $auser->status=0
$picture = $OUTPUT->user_picture($auser);
if (empty($auser->submissionid)) {
@@ -1552,9 +1571,11 @@ class assignment_base {
$mform->addElement('text', 'perpage', get_string('pagesize', 'assignment'), array('size'=>1));
$mform->setDefault('perpage', $perpage);
$mform->addElement('checkbox', 'quickgrade', get_string('quickgrade','assignment'));
$mform->setDefault('quickgrade', $quickgrade);
$mform->addHelpButton('quickgrade', 'quickgrade', 'assignment');
if ($this->quickgrade_mode_allowed()) {
$mform->addElement('checkbox', 'quickgrade', get_string('quickgrade','assignment'));
$mform->setDefault('quickgrade', $quickgrade);
$mform->addHelpButton('quickgrade', 'quickgrade', 'assignment');
}
$mform->addElement('submit', 'savepreferences', get_string('savepreferences'));
@@ -2352,11 +2373,12 @@ class mod_assignment_grading_form extends moodleform {
$mform->addElement('header', 'Grades', get_string('grades', 'grades'));
$grademenu = make_grades_menu($this->_customdata->assignment->grade);
if ($gradinginstance = $this->use_advanced_grading()) {
$gradinginstance->get_controller()->set_grade_range($grademenu);
$mform->addElement('grading', 'advancedgrading', get_string('grade').':', array('gradinginstance' => $gradinginstance));
} else {
// use simple direct grading
$grademenu = make_grades_menu($this->_customdata->assignment->grade);
$grademenu['-1'] = get_string('nograde');
$mform->addElement('select', 'xgrade', get_string('grade').':', $grademenu, $attributes);