From 4dc81cc70de2089b5a5c1250ddbb67c923a2b525 Mon Sep 17 00:00:00 2001 From: nicolasconnault Date: Fri, 10 Oct 2008 07:18:19 +0000 Subject: [PATCH] MDL-15680 Added grade category aggregation settings and weights, plus correct handling of 3 types of weights. --- grade/edit/tree/item_form.php | 6 +- grade/edit/weights/ajax.php | 45 +++++--- grade/edit/weights/index.php | 125 +++++++++++++++------ grade/edit/weights/lib.php | 199 ++++++++++++++++++++++++++++++++++ grade/edit/weights/tree.css | 35 ++++++ grade/report/grader/lib.php | 32 +----- lang/en_utf8/grades.php | 7 ++ lib/grade/grade_item.php | 35 ++++++ pix/t/nonempty.gif | Bin 0 -> 94 bytes pix/t/sigmaplus.gif | Bin 0 -> 130 bytes 10 files changed, 398 insertions(+), 86 deletions(-) create mode 100644 grade/edit/weights/lib.php create mode 100644 pix/t/nonempty.gif create mode 100644 pix/t/sigmaplus.gif diff --git a/grade/edit/tree/item_form.php b/grade/edit/tree/item_form.php index 8b203e1f123..3f1fee6c180 100644 --- a/grade/edit/tree/item_form.php +++ b/grade/edit/tree/item_form.php @@ -136,15 +136,13 @@ class edit_item_form extends moodleform { $mform->addElement('header', 'headerparent', get_string('parentcategory', 'grades')); $options = array(); - $default = ''; $coefstring = ''; $categories = grade_category::fetch_all(array('courseid'=>$COURSE->id)); + foreach ($categories as $cat) { $cat->apply_forced_settings(); $options[$cat->id] = $cat->get_name(); - if ($cat->is_course_category()) { - $default = $cat->id; - } + if ($cat->is_aggregationcoef_used()) { if ($cat->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN) { $coefstring = ($coefstring=='' or $coefstring=='aggregationcoefweight') ? 'aggregationcoefweight' : 'aggregationcoef'; diff --git a/grade/edit/weights/ajax.php b/grade/edit/weights/ajax.php index 393a48fba62..5dff7f66c93 100755 --- a/grade/edit/weights/ajax.php +++ b/grade/edit/weights/ajax.php @@ -22,36 +22,47 @@ YAHOO.grade_edit_weights.buildTreeNode = function(element, parentNode) { } if (element.item.table == 'grade_categories') { - var tmpNode = new YAHOO.widget.TextNode(element.item.name, parentNode, parentNode.isRoot()); + var aggregation_types = ''+ + element.item.name + '<'+'/span>'; + var tmpNode = new YAHOO.widget.HTMLNode(gradeitem, parentNode, false); } }; YAHOO.grade_edit_weights.init = function() { var gew = YAHOO.grade_edit_weights; var div = document.getElementById('weightstree'); - gew.tree = new YAHOO.widget.TreeView('weightstree'); + gew.tree = new YAHOO.widget.TreeView('gradetree'); - //handler for expanding all nodes - YAHOO.util.Event.on("expand", "click", function(e) { - YAHOO.log("Expanding all TreeView nodes.", "info", "example"); - gew.tree.expandAll(); - YAHOO.util.Event.preventDefault(e); - }); + //handler for expanding all nodes + YAHOO.util.Event.on("expand", "click", function(e) { + YAHOO.log("Expanding all TreeView nodes.", "info", "example"); + gew.tree.expandAll(); + YAHOO.util.Event.preventDefault(e); + }); - //handler for collapsing all nodes - YAHOO.util.Event.on("collapse", "click", function(e) { - YAHOO.log("Collapsing all TreeView nodes.", "info", "example"); - gew.tree.collapseAll(); - YAHOO.util.Event.preventDefault(e); - }); + //handler for collapsing all nodes + YAHOO.util.Event.on("collapse", "click", function(e) { + YAHOO.log("Collapsing all TreeView nodes.", "info", "example"); + gew.tree.collapseAll(); + YAHOO.util.Event.preventDefault(e); + }); - gew.buildTreeNode(); - gew.tree.draw(); + // gew.buildTreeNode(); + gew.tree.render(); + gew.tree.expandAll(); }; YAHOO.util.Event.onDOMReady(YAHOO.grade_edit_weights.init); diff --git a/grade/edit/weights/index.php b/grade/edit/weights/index.php index 6a1ec1143f8..d7428b5c9b1 100755 --- a/grade/edit/weights/index.php +++ b/grade/edit/weights/index.php @@ -26,10 +26,13 @@ require_once '../../../config.php'; require_once $CFG->dirroot.'/grade/lib.php'; require_once $CFG->dirroot.'/grade/report/lib.php'; // for preferences +require_once $CFG->dirroot.'/grade/edit/weights/lib.php'; -$courseid = required_param('id', PARAM_INT); -$action = optional_param('action', 0, PARAM_ALPHA); -$eid = optional_param('eid', 0, PARAM_ALPHANUM); +$courseid = required_param('id', PARAM_INT); +$action = optional_param('action', 0, PARAM_ALPHA); +$eid = optional_param('eid', 0, PARAM_ALPHANUM); +$category = optional_param('category', null, PARAM_INT); +$aggregationtype = optional_param('aggregationtype', null, PARAM_INT); require_js(array('yui_yahoo', 'yui_dom', 'yui_event', 'yui_json', 'yui_connection', 'yui_dragdrop', 'yui_treeview')); @@ -44,9 +47,19 @@ $context = get_context_instance(CONTEXT_COURSE, $course->id); require_capability('moodle/grade:manage', $context); /// return tracking object -$gpr = new grade_plugin_return(array('type'=>'edit', 'plugin'=>'weight', 'courseid'=>$courseid)); +$gpr = new grade_plugin_return(array('type'=>'edit', 'plugin'=>'weights', 'courseid'=>$courseid)); $returnurl = $gpr->get_return_url(null); +// Change category aggregation if requested +if (!is_null($category) && !is_null($aggregationtype)) { + if (!$grade_category = grade_category::fetch(array('id'=>$category, 'courseid'=>$courseid))) { + error('Incorrect category id!'); + } + $data->aggregation = $aggregationtype; + grade_category::set_properties($grade_category, $data); + $grade_category->update(); +} + //first make sure we have proper final grades - we need it for locking changes grade_regrade_final_grades($courseid); @@ -64,57 +77,97 @@ $strcategoriesanditems = get_string('categoriesanditems', 'grades'); $navigation = grade_build_nav(__FILE__, $strcategoriesanditems, array('courseid' => $courseid)); $moving = false; -switch ($action) { - default: - break; -} - $CFG->stylesheets[] = $CFG->wwwroot.'/grade/edit/weights/tree.css'; print_header_simple($strgrades . ': ' . $strgraderreport, ': ' . $strcategoriesedit, $navigation, '', '', true, '', navmenu($course)); /// Print the plugin selector at the top print_grade_plugin_selector($courseid, 'edit', 'tree'); -print_heading(get_string('categoriesedit', 'grades')); +print_heading(get_string('weightsedit', 'grades')); $tree_json = json_encode(get_tree_json($gtree, $gtree->top_element)); -require_once('ajax.php'); +$form_key = optional_param('sesskey', null, PARAM_ALPHANUM); + +if ($form_key) { + $data = data_submitted(); + + foreach ($data as $key => $value) { + if (preg_match('/aggregation_type_([0-9]*)/', $key, $matches)) { + $aggtype = required_param($matches[0], PARAM_INT); + $a->id = $matches[1]; + + if (!$DB->update_record('grade_categories', array('id' => $matches[1], 'aggregation' => $aggtype))) { + print_error('errorupdatinggradecategoryaggregation', 'grades', $a); + } + + } elseif (preg_match('/weight_([0-9]*)/', $key, $matches)) { + $weight = required_param($matches[0], PARAM_NUMBER); + $a->id = $matches[1]; + + if (!$DB->update_record('grade_items', array('id' => $matches[1], 'aggregationcoef' => $weight))) { + print_error('errorupdatinggradeitemaggregationcoef', 'grades', $a); + } + + } elseif (preg_match('/extracredit_original_([0-9]*)/', $key, $matches)) { // Sum extra credit checkbox + $extracredit = optional_param("extracredit_{$matches[1]}", null, PARAM_BOOL); + $original_value = required_param($matches[0], PARAM_BOOL); + $a->id = $matches[1]; + $newvalue = null; + + if ($original_value == 1 && is_null($extracredit)) { + $newvalue = 0; + } elseif ($original_value == 0 && $extracredit == 1) { + $newvalue = 1; + } else { + continue; + } + + if (!$DB->update_record('grade_items', array('id' => $matches[1], 'aggregationcoef' => $newvalue))) { + print_error('errorupdatinggradeitemaggregationcoef', 'grades', $a); + } + + } elseif (preg_match('/aggregate(onlygraded|subcats|outcomes)_original_([0-9]*)/', $key, $matches)) { + $setting = optional_param('aggregate'.$matches[1].'_'.$matches[2], null, PARAM_BOOL); + $original_value = required_param($matches[0], PARAM_BOOL); + $a->id = $matches[2]; + + $newvalue = null; + if ($original_value == 1 && is_null($setting)) { + $newvalue = 0; + } elseif ($original_value == 0 && $setting == 1) { + $newvalue = 1; + } else { + continue; + } + + if (!$DB->update_record('grade_categories', array('id' => $matches[2], 'aggregate'.$matches[1] => $newvalue))) { + print_error('errorupdatinggradecategoryaggregate'.$matches[1], 'grades', $a); + } + } + } +} + +// AJAX interface not really needed: adds nice tree functions but not very useful +// require_once('ajax.php'); print_box_start('gradetreebox generalbox'); -echo '
- Expand all - Collapse all -
'; +// echo '
Expand all Collapse all
'; echo '
'; -echo '
'; +echo ''; +echo '
'; +echo build_html_tree(get_tree_json($gtree, $gtree->top_element), null, $returnurl); // print_grade_tree($gtree, $gtree->top_element, $gpr, $switch); // -echo '
'; -echo ''; +echo '
'; + +echo ''; +echo '
'; print_box_end(); print_footer($course); die; -function get_tree_json(&$gtree, $element) { - - $return_array = array(); - - $object = $element['object']; - $eid = $element['eid']; - $object->name = $gtree->get_element_header($element, false, false, false); - - $return_array['item'] = $object; - - if ($element['type'] == 'category') { - foreach($element['children'] as $child_el) { - $return_array['children'][] = get_tree_json($gtree, $child_el); - } - } - - return $return_array; -} ?> diff --git a/grade/edit/weights/lib.php b/grade/edit/weights/lib.php new file mode 100644 index 00000000000..ef53634fa64 --- /dev/null +++ b/grade/edit/weights/lib.php @@ -0,0 +1,199 @@ +name = $gtree->get_element_header($element, false, false, false); + + $return_array['item'] = $object; + + if ($element['type'] == 'category') { + foreach($element['children'] as $child_el) { + if (!empty($child_el['object']->itemtype) && ($child_el['object']->itemtype == 'course' || $child_el['object']->itemtype == 'category') && !$totals) { + continue; + } + $return_array['children'][] = get_tree_json($gtree, $child_el); + } + } + + return $return_array; +} + +function build_html_tree($tree, $element=null) { + global $CFG; + + $options = array(GRADE_AGGREGATE_MEAN =>get_string('aggregatemean', 'grades'), + GRADE_AGGREGATE_WEIGHTED_MEAN =>get_string('aggregateweightedmean', 'grades'), + GRADE_AGGREGATE_WEIGHTED_MEAN2 =>get_string('aggregateweightedmean2', 'grades'), + GRADE_AGGREGATE_EXTRACREDIT_MEAN=>get_string('aggregateextracreditmean', 'grades'), + GRADE_AGGREGATE_MEDIAN =>get_string('aggregatemedian', 'grades'), + GRADE_AGGREGATE_MIN =>get_string('aggregatemin', 'grades'), + GRADE_AGGREGATE_MAX =>get_string('aggregatemax', 'grades'), + GRADE_AGGREGATE_MODE =>get_string('aggregatemode', 'grades'), + GRADE_AGGREGATE_SUM =>get_string('aggregatesum', 'grades')); + + $html = ''; + $root = false; + + if (is_null($element)) { + $html .= "\n"; + } + + return $html; +} + +/** + * Given a grade_item object, returns a labelled input if an aggregation coefficient (weight or extra credit) applies to it. + * @param grade_item $item + * @return string HTML + */ +function get_weight_input($item) { + if ($item->is_course_item()) { + return ''; + } + + $parent_category = $item->get_parent_category(); + + if ($item->is_category_item()) { + $parent_category = $parent_category->get_parent_category(); + } + + $parent_category->apply_forced_settings(); + + if ($parent_category->is_aggregationcoef_used()) { + $aggcoef = ''; + + if ($parent_category->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN) { + $aggcoef = 'aggregationcoefweight'; + } elseif ($parent_category->aggregation == GRADE_AGGREGATE_EXTRACREDIT_MEAN) { + $aggcoef = 'aggregationcoefextra'; + } elseif ($parent_category->aggregation == GRADE_AGGREGATE_SUM) { + $aggcoef = 'aggregationcoefextrasum'; + } + + if ($aggcoef == 'aggregationcoefweight' || $aggcoef == 'aggregationcoefextra') { + return '' + . ''; + } elseif ($aggcoef == 'aggregationcoefextrasum' ) { + $checked = ($item->aggregationcoef > 0) ? 'checked="checked"' : ''; + $extracredit = ($item->aggregationcoef > 0) ? 1 : 0; + + return '' + . '\n" + . ''; + } else { + return ''; + } + } +} +?> diff --git a/grade/edit/weights/tree.css b/grade/edit/weights/tree.css index d70421942fc..dcdbc8b95af 100644 --- a/grade/edit/weights/tree.css +++ b/grade/edit/weights/tree.css @@ -134,3 +134,38 @@ padding:1em; margin-top:1em; } + +span.gradeitem input { + margin-right: 10px; +} + +span.gradeitem label, +li.category label.weight { + margin-right: 10px; +} + +li.category label.weight { + margin-left: 5px; +} + +li.category span.name { + font-weight: bold; +} + +img.caticon { + width: 11px; + height: 11px; + margin: 0px -1px 3px 5px; +} + +#gradetree select { + margin-left: 10px; +} + +li.category { + margin-top: 10px; +} + +li.category ul { + margin-top: 10px; +} diff --git a/grade/report/grader/lib.php b/grade/report/grader/lib.php index 89c42f319f6..1cbcdeb0c29 100644 --- a/grade/report/grader/lib.php +++ b/grade/report/grader/lib.php @@ -1091,40 +1091,14 @@ class grade_report_grader extends grade_report { foreach ($this->gtree->get_items() as $itemid=>$unused) { $item =& $this->gtree->get_item($itemid); - // Determine which display type to use for this average - if ($USER->gradeediting[$this->courseid]) { - $displaytype = GRADE_DISPLAY_TYPE_REAL; - - } else if ($rangesdisplaytype == GRADE_REPORT_PREFERENCE_INHERIT) { // no ==0 here, please resave report and user prefs - $displaytype = $item->get_displaytype(); - - } else { - $displaytype = $rangesdisplaytype; - } - - // Override grade_item setting if a display preference (not default) was set for the averages - if ($rangesdecimalpoints == GRADE_REPORT_PREFERENCE_INHERIT) { - $decimalpoints = $item->get_decimals(); - - } else { - $decimalpoints = $rangesdecimalpoints; - } - - if ($displaytype == GRADE_DISPLAY_TYPE_PERCENTAGE) { - $grademin = "0 %"; - $grademax = "100 %"; - - } else { - $grademin = grade_format_gradevalue($item->grademin, $item, true, $displaytype, $decimalpoints); - $grademax = grade_format_gradevalue($item->grademax, $item, true, $displaytype, $decimalpoints); - } - $hidden = ''; if ($item->is_hidden()) { $hidden = ' hidden '; } - $scalehtml .= ''. $grademin.'–'. $grademax.''; + $formatted_range = $item->get_formatted_range($rangesdisplaytype, $rangesdecimalpoints); + + $scalehtml .= ''. $formatted_range .''; } $scalehtml .= ''; } diff --git a/lang/en_utf8/grades.php b/lang/en_utf8/grades.php index 69e99100cd9..fe6b2a760d5 100644 --- a/lang/en_utf8/grades.php +++ b/lang/en_utf8/grades.php @@ -153,6 +153,11 @@ $string['errornocalculationallowed'] = 'Calculations are not allowed for this it $string['errornocategorisedid'] = 'Could not get an uncategorised id!'; $string['errornocourse'] = 'Could not get course information'; $string['errorreprintheadersnonnumeric'] = 'Received non-numeric value for reprint-headers'; +$string['errorupdatinggradecategoryaggregateonlygraded'] = 'Error updating the \"Aggregate only graded items\" setting of of grade category ID $a->id'; +$string['errorupdatinggradecategoryaggregateoutcomes'] = 'Error updating the \"Aggregate outcomes\" setting of of grade category ID $a->id'; +$string['errorupdatinggradecategoryaggregatesubcats'] = 'Error updating the \"Aggregate sub-categories\" setting of of grade category ID $a->id'; +$string['errorupdatinggradecategoryaggregation'] = 'Error updating the aggregation type of grade category ID $a->id'; +$string['errorupdatinggradeitemaggregationcoef'] = 'Error updating the aggregation coefficient (weight or extra credit) of grade item ID $a->id'; $string['exceptions'] = 'Exceptions'; $string['excluded'] = 'Excluded'; $string['excludedhelp'] = 'If -excluded- is switched on, this grade will be excluded from any aggregation performed by any parent grade item or category.'; @@ -514,6 +519,8 @@ $string['weightedascending'] = 'Sort by weighted percent ascending'; $string['weighteddescending'] = 'Sort by weighted percent descending'; $string['weightedpct'] = 'weighted %%'; $string['weightedpctcontribution'] = 'weighted %% contribution'; +$string['weights'] = 'Weights'; +$string['weightsedit'] = 'Edit weights and extra credits'; $string['writinggradebookinfo'] = 'Writing gradebook settings'; $string['xml'] = 'XML'; $string['yes'] = 'Yes'; diff --git a/lib/grade/grade_item.php b/lib/grade/grade_item.php index fba8038e442..c56331798b6 100644 --- a/lib/grade/grade_item.php +++ b/lib/grade/grade_item.php @@ -1893,5 +1893,40 @@ class grade_item extends grade_object { return $this->decimals; } } + + function get_formatted_range($rangesdisplaytype=null, $rangesdecimalpoints=null) { + + global $USER; + + // Determine which display type to use for this average + if (isset($USER->gradeediting) && $USER->gradeediting[$this->courseid]) { + $displaytype = GRADE_DISPLAY_TYPE_REAL; + + } else if ($rangesdisplaytype == GRADE_REPORT_PREFERENCE_INHERIT) { // no ==0 here, please resave report and user prefs + $displaytype = $this->get_displaytype(); + + } else { + $displaytype = $rangesdisplaytype; + } + + // Override grade_item setting if a display preference (not default) was set for the averages + if ($rangesdecimalpoints == GRADE_REPORT_PREFERENCE_INHERIT) { + $decimalpoints = $this->get_decimals(); + + } else { + $decimalpoints = $rangesdecimalpoints; + } + + if ($displaytype == GRADE_DISPLAY_TYPE_PERCENTAGE) { + $grademin = "0 %"; + $grademax = "100 %"; + + } else { + $grademin = grade_format_gradevalue($this->grademin, $this, true, $displaytype, $decimalpoints); + $grademax = grade_format_gradevalue($this->grademax, $this, true, $displaytype, $decimalpoints); + } + + return $grademin.'–'. $grademax; + } } ?> diff --git a/pix/t/nonempty.gif b/pix/t/nonempty.gif new file mode 100644 index 0000000000000000000000000000000000000000..5b65b2c394a374820130f9ee699e1892530aaca2 GIT binary patch literal 94 zcmZ?wbhEHb