diff --git a/grade/edit/tree/category_form.php b/grade/edit/tree/category_form.php index 37a100f35c3..03007c6d5ca 100644 --- a/grade/edit/tree/category_form.php +++ b/grade/edit/tree/category_form.php @@ -11,31 +11,32 @@ class edit_category_form extends moodleform { $mform->addElement('header', 'general', get_string('gradecategory', 'grades')); $mform->addElement('text', 'fullname', get_string('categoryname', 'grades')); - $options = array(GRADE_AGGREGATE_MEAN_ALL =>get_string('aggregatemeanall', 'grades'), - GRADE_AGGREGATE_MEAN_GRADED =>get_string('aggregatemeangraded', 'grades'), - GRADE_AGGREGATE_MEDIAN_ALL =>get_string('aggregatemedianall', 'grades'), - GRADE_AGGREGATE_MEDIAN_GRADED =>get_string('aggregatemediangraded', 'grades'), - GRADE_AGGREGATE_MIN_ALL =>get_string('aggregateminall', 'grades'), - GRADE_AGGREGATE_MIN_GRADED =>get_string('aggregatemingraded', 'grades'), - GRADE_AGGREGATE_MAX_ALL =>get_string('aggregatemaxall', 'grades'), - GRADE_AGGREGATE_MAX_GRADED =>get_string('aggregatemaxgraded', 'grades'), - GRADE_AGGREGATE_MODE_ALL =>get_string('aggregatemodeall', 'grades'), - GRADE_AGGREGATE_MODE_GRADED =>get_string('aggregatemodegraded', 'grades'), - GRADE_AGGREGATE_WEIGHTED_MEAN_ALL =>get_string('aggregateweightedmeanall', 'grades'), - GRADE_AGGREGATE_WEIGHTED_MEAN_GRADED =>get_string('aggregateweightedmeangraded', 'grades'), - GRADE_AGGREGATE_EXTRACREDIT_MEAN_ALL =>get_string('aggregateextracreditmeanall', 'grades'), - GRADE_AGGREGATE_EXTRACREDIT_MEAN_GRADED=>get_string('aggregateextracreditmeangraded', 'grades')); + $options = array(GRADE_AGGREGATE_MEAN =>get_string('aggregatemean', '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_WEIGHTED_MEAN =>get_string('aggregateweightedmean', 'grades'), + GRADE_AGGREGATE_EXTRACREDIT_MEAN=>get_string('aggregateextracreditmean', 'grades')); $mform->addElement('select', 'aggregation', get_string('aggregation', 'grades'), $options); $mform->setHelpButton('aggregation', array('aggregation', get_string('aggregation', 'grades'), 'grade')); - $mform->setDefault('gradetype', GRADE_AGGREGATE_MEAN_ALL); + $mform->setDefault('gradetype', GRADE_AGGREGATE_MEAN); + + $mform->addElement('advcheckbox', 'aggregateonlygraded', get_string('aggregateonlygraded', 'grades')); + $mform->setHelpButton('aggregateonlygraded', array(false, get_string('aggregateonlygraded', 'grades'), + false, true, false, get_string('aggregateonlygradedhelp', 'grades'))); if (!empty($CFG->enableoutcomes)) { $mform->addElement('advcheckbox', 'aggregateoutcomes', get_string('aggregateoutcomes', 'grades')); $mform->setHelpButton('aggregateoutcomes', array(false, get_string('aggregateoutcomes', 'grades'), - false, true, false, get_string("aggregateoutcomeshelp", 'grades'))); + false, true, false, get_string('aggregateoutcomeshelp', 'grades'))); } + $mform->addElement('advcheckbox', 'aggregatesubcats', get_string('aggregatesubcats', 'grades')); + $mform->setHelpButton('aggregatesubcats', array(false, get_string('aggregatesubcats', 'grades'), + false, true, false, get_string('aggregatesubcatshelp', 'grades'))); + $options = array(); $options[0] = get_string('none'); for ($i=1; $i<=20; $i++) { @@ -43,12 +44,12 @@ class edit_category_form extends moodleform { } $mform->addElement('select', 'keephigh', get_string('keephigh', 'grades'), $options); $mform->setHelpButton('keephigh', array(false, get_string('keephigh', 'grades'), - false, true, false, get_string("keephighhelp", 'grades'))); + false, true, false, get_string('keephighhelp', 'grades'))); $mform->disabledIf('keephigh', 'droplow', 'noteq', 0); $mform->addElement('select', 'droplow', get_string('droplow', 'grades'), $options); $mform->setHelpButton('droplow', array(false, get_string('droplow', 'grades'), - false, true, false, get_string("droplowhelp", 'grades'))); + false, true, false, get_string('droplowhelp', 'grades'))); $mform->disabledIf('droplow', 'keephigh', 'noteq', 0); // user preferences @@ -61,7 +62,7 @@ class edit_category_form extends moodleform { . ': ' . $options[$CFG->grade_report_aggregationview] . ')'; $mform->addElement('select', 'pref_aggregationview', $label, $options); $mform->setHelpButton('pref_aggregationview', array(false, get_string('aggregationview', 'grades'), - false, true, false, get_string("configaggregationview", 'grades'))); + false, true, false, get_string('configaggregationview', 'grades'))); $mform->setDefault('pref_aggregationview', GRADE_REPORT_PREFERENCE_DEFAULT); // hidden params @@ -102,6 +103,15 @@ class edit_category_form extends moodleform { if ($mform->elementExists('droplow')) { $mform->removeElement('droplow'); } + if ($mform->elementExists('aggregateonlygraded')) { + $mform->removeElement('aggregateonlygraded'); + } + if ($mform->elementExists('aggregateoutcomes')) { + $mform->removeElement('aggregateoutcomes'); + } + if ($mform->elementExists('aggregatesubcats')) { + $mform->removeElement('aggregatesubcats'); + } } } } diff --git a/grade/report/grader/lib.php b/grade/report/grader/lib.php index 7fd39de2558..7b549eebb7d 100644 --- a/grade/report/grader/lib.php +++ b/grade/report/grader/lib.php @@ -852,7 +852,7 @@ class grade_report_grader extends grade_report { $ungraded_count = get_field_sql($SQL); - if ($meanselection == GRADE_AGGREGATE_MEAN_GRADED) { + if ($meanselection == GRADE_REPORT_MEAN_GRADED) { $mean_count = $totalcount - $ungraded_count; } else { // Bump up the sum by the number of ungraded items * grademin if (isset($sum_array[$item->id])) { diff --git a/grade/report/grader/preferences_form.php b/grade/report/grader/preferences_form.php index 75644c450fd..592d15d58e0 100644 --- a/grade/report/grader/preferences_form.php +++ b/grade/report/grader/preferences_form.php @@ -52,8 +52,8 @@ class grader_report_preferences_form extends moodleform { GRADE_REPORT_GRADE_DISPLAY_TYPE_PERCENTAGE => get_string('percentage', 'grades'), GRADE_REPORT_GRADE_DISPLAY_TYPE_LETTER => get_string('letter', 'grades')), 'meanselection' => array(GRADE_REPORT_PREFERENCE_DEFAULT => 'default', - GRADE_AGGREGATE_MEAN_ALL => get_string('meanall', 'grades'), - GRADE_AGGREGATE_MEAN_GRADED => get_string('meangraded', 'grades')), + GRADE_REPORT_MEAN_ALL => get_string('meanall', 'grades'), + GRADE_REPORT_MEAN_GRADED => get_string('meangraded', 'grades')), 'enableajax' => $checkbox_default); $preferences['prefshow'] = array('showcalculations' => $checkbox_default, diff --git a/grade/report/grader/settings.php b/grade/report/grader/settings.php index 064f34b9dd8..d63ea3d9c56 100644 --- a/grade/report/grader/settings.php +++ b/grade/report/grader/settings.php @@ -47,8 +47,8 @@ $settings->add(new admin_setting_configselect('grade_report_gradedisplaytype', g $settings->add(new admin_setting_configselect('grade_report_meanselection', get_string('meanselection', 'grades'), get_string('configmeanselection', 'grades'), false, - array(GRADE_AGGREGATE_MEAN_ALL => get_string('meanall', 'grades'), - GRADE_AGGREGATE_MEAN_GRADED => get_string('meangraded', 'grades')))); + array(GRADE_REPORT_MEAN_ALL => get_string('meanall', 'grades'), + GRADE_REPORT_MEAN_GRADED => get_string('meangraded', 'grades')))); $settings->add(new admin_setting_configcheckbox('grade_report_enableajax', get_string('enableajax', 'grades'), get_string('configenableajax', 'grades'), 0)); diff --git a/lang/en_utf8/grades.php b/lang/en_utf8/grades.php index 8f5e8e62404..f164af6220d 100644 --- a/lang/en_utf8/grades.php +++ b/lang/en_utf8/grades.php @@ -10,23 +10,20 @@ $string['addfeedback'] = 'Add Feedback'; $string['addidnumbers'] = 'Add id numbers'; $string['additem'] = 'Add Grade Item'; $string['addoutcomeitem'] = 'Add Outcome Item'; -$string['aggregateextracreditmeanall'] = 'Mean of all grades (extra credits)'; -$string['aggregateextracreditmeangraded'] = 'Mean of non-empty grades (extra credits)'; -$string['aggregatemeanall'] = 'Mean of all grades'; -$string['aggregatemeangraded'] = 'Mean of non-empty grades'; -$string['aggregatemedianall'] = 'Median of all grades'; -$string['aggregatemediangraded'] = 'Median of non-empty grades'; -$string['aggregateminall'] = 'Smallest grade of all grades'; -$string['aggregatemingraded'] = 'Smallest grade of non-empty grades'; -$string['aggregatemaxall'] = 'Highest grade of all grades'; -$string['aggregatemaxgraded'] = 'Highest grade of non-empty grades'; -$string['aggregatemodeall'] = 'Mode of all grades'; -$string['aggregatemodegraded'] = 'Mode of non-empty grades'; +$string['aggregateextracreditmean'] = 'Mean of grades (with extra credits)'; +$string['aggregatemean'] = 'Mean of grades'; +$string['aggregatemedian'] = 'Median of grades'; +$string['aggregatemin'] = 'Smallest grade'; +$string['aggregatemax'] = 'Highest grade'; +$string['aggregatemode'] = 'Mode of grades'; +$string['aggregateonlygraded'] = 'Aggregate only non-empty grades'; +$string['aggregateonlygradedhelp'] = 'Nonexistent grades are either treated as minimal grades or not included in aggregation.'; $string['aggregateoutcomes'] = 'Include outcomes in aggregation'; $string['aggregateoutcomeshelp'] = 'Including outcomes in aggregation may not lead to the desired overall grade, so you have the option to include or leave them out.'; +$string['aggregatesubcats'] = 'Aggregate including subcategories'; +$string['aggregatesubcatshelp'] = 'The aggregation is usually done only with immediate children, it is also possible to aggregate grades in all subcategories excluding other aggregated grades.'; $string['aggregatesonly'] = 'Aggregates only'; -$string['aggregateweightedmeanall'] = 'Weighted mean of all grades'; -$string['aggregateweightedmeangraded'] = 'Weighted mean of non-empty grades'; +$string['aggregateweightedmean'] = 'Weighted mean of grades'; $string['aggregation'] = 'Aggregation'; $string['aggregationcoef'] = 'Aggregation coefficient'; $string['aggregationcoefhelp'] = 'Weight applied to all grades in this grade item during aggregation with other grade items.'; diff --git a/lib/db/install.xml b/lib/db/install.xml index c17ab0e18f0..341b3e41f14 100644 --- a/lib/db/install.xml +++ b/lib/db/install.xml @@ -1,5 +1,5 @@ - @@ -1291,9 +1291,11 @@ - - - + + + + + @@ -1434,8 +1436,10 @@ - - + + + + diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index f16b96984d1..20a7b0e9cf9 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -967,28 +967,6 @@ function xmldb_main_upgrade($oldversion=0) { } if ($result && $oldversion < 2007072200) { -/// Remove obsoleted unit tests tables - they will be recreated automatically - $tables = array('grade_categories', - 'scale', - 'grade_items', - 'grade_calculations', - 'grade_grades', - 'grade_grades_raw', - 'grade_grades_final', - 'grade_grades_text', - 'grade_outcomes', - 'grade_outcomes_courses'); - - foreach ($tables as $tablename) { - $table = new XMLDBTable('unittest_'.$tablename); - if (table_exists($table)) { - drop_table($table); - } - $table = new XMLDBTable('unittest_'.$tablename.'_history'); - if (table_exists($table)) { - drop_table($table); - } - } /// Remove all grade tables used in development phases - we need new empty tables for final gradebook upgrade $tables = array('grade_categories', @@ -1063,7 +1041,9 @@ function xmldb_main_upgrade($oldversion=0) { $table->addFieldInfo('aggregation', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, null, '0'); $table->addFieldInfo('keephigh', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, null, '0'); $table->addFieldInfo('droplow', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, null, '0'); + $table->addFieldInfo('aggregateonlygraded', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $table->addFieldInfo('aggregateoutcomes', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); + $table->addFieldInfo('aggregatesubcats', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $table->addFieldInfo('timecreated', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('timemodified', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); @@ -1231,7 +1211,9 @@ function xmldb_main_upgrade($oldversion=0) { $table->addFieldInfo('aggregation', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, null, '0'); $table->addFieldInfo('keephigh', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, null, '0'); $table->addFieldInfo('droplow', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, null, '0'); + $table->addFieldInfo('aggregateonlygraded', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $table->addFieldInfo('aggregateoutcomes', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); + $table->addFieldInfo('aggregatesubcats', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); /// Adding keys to table grade_categories_history $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); @@ -1761,24 +1743,6 @@ function xmldb_main_upgrade($oldversion=0) { $result = $result && add_field($table, $field); } -/* - /// drop old gradebook tables - if ($result && $oldversion < 2007072209) { - $tables = array('grade_category', - 'grade_item', - 'grade_letter', - 'grade_preferences', - 'grade_exceptions'); - - foreach ($tables as $table) { - $table = new XMLDBTable($table); - if (table_exists($table)) { - drop_table($table); - } - } - } -*/ - if ($result && $oldversion < 2007082700) { /// Define field timemodified to be added to tag_instance @@ -1798,6 +1762,7 @@ function xmldb_main_upgrade($oldversion=0) { foreach ($tags as $oldtag) { // if this tag does not exist in tag table yet if (!$newtag = get_record('tag', 'name', tag_normalize($oldtag->text))) { + $itag = new object(); $itag->name = tag_normalize($oldtag->text); $itag->rawname = tag_normalize($oldtag->text, false); @@ -1991,6 +1956,104 @@ function xmldb_main_upgrade($oldversion=0) { } + if ($result && $oldversion < 2007090503) { +/// Remove obsoleted unit tests tables - they will be recreated automatically + $tables = array('grade_categories', + 'scale', + 'grade_items', + 'grade_calculations', + 'grade_grades', + 'grade_grades_raw', + 'grade_grades_final', + 'grade_grades_text', + 'grade_outcomes', + 'grade_outcomes_courses'); + + foreach ($tables as $tablename) { + $table = new XMLDBTable('unittest_'.$tablename); + if (table_exists($table)) { + drop_table($table); + } + $table = new XMLDBTable('unittest_'.$tablename.'_history'); + if (table_exists($table)) { + drop_table($table); + } + } + + + /// Define field aggregatesubcats to be added to grade_categories + $table = new XMLDBTable('grade_categories'); + $field = new XMLDBField('aggregatesubcats'); + $field->setAttributes(XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'aggregateoutcomes'); + + if (!field_exists($table, $field)) { + /// Launch add field aggregateonlygraded + $result = $result && add_field($table, $field); + } + + /// Define field aggregateonlygraded to be added to grade_categories + $table = new XMLDBTable('grade_categories'); + $field = new XMLDBField('aggregateonlygraded'); + $field->setAttributes(XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'droplow'); + + if (!field_exists($table, $field)) { + /// Launch add field aggregateonlygraded + $result = $result && add_field($table, $field); + } + + /// Define field aggregatesubcats to be added to grade_categories_history + $table = new XMLDBTable('grade_categories_history'); + $field = new XMLDBField('aggregatesubcats'); + $field->setAttributes(XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'aggregateoutcomes'); + + if (!field_exists($table, $field)) { + /// Launch add field aggregateonlygraded + $result = $result && add_field($table, $field); + } + + /// Define field aggregateonlygraded to be added to grade_categories_history + $table = new XMLDBTable('grade_categories_history'); + $field = new XMLDBField('aggregateonlygraded'); + $field->setAttributes(XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'droplow'); + + if (!field_exists($table, $field)) { + /// Launch add field aggregateonlygraded + $result = $result && add_field($table, $field); + } + + /// upgrade path in grade_categrories table - now using slash on both ends + $concat = sql_concat('path', "'/'"); + $sql = "UPDATE {$CFG->prefix}grade_categories SET path = $concat WHERE path NOT LIKE '/%/'"; + execute_sql($sql, true); + + /// convert old aggregation constants if needed + for ($i=0; $i<=12; $i=$i+2) { + $j = $i+1; + $sql = "UPDATE {$CFG->prefix}grade_categories SET aggregation = $i, aggregateonlygraded = 1 WHERE aggregation = $j"; + execute_sql($sql, true); + } + } + + + +/* + /// drop old gradebook tables + if ($result && $oldversion < xxxxxxxx) { + $tables = array('grade_category', + 'grade_item', + 'grade_letter', + 'grade_preferences', + 'grade_exceptions'); + + foreach ($tables as $table) { + $table = new XMLDBTable($table); + if (table_exists($table)) { + drop_table($table); + } + } + } +*/ + return $result; } diff --git a/lib/db/upgradelib.php b/lib/db/upgradelib.php index 8d0525dd210..a76c83e6e75 100644 --- a/lib/db/upgradelib.php +++ b/lib/db/upgradelib.php @@ -41,7 +41,7 @@ function upgrade_18_gradebook($courseid) { $course_category->courseid = $courseid; $course_category->fullname = get_string('coursegradecategory', 'grades'); $course_category->parent = null; - $course_category->aggregation = GRADE_AGGREGATE_MEAN_ALL; + $course_category->aggregation = GRADE_AGGREGATE_MEAN; $course_category->timemodified = $course_category->timecreated = time(); if (!$course_category->id = insert_record('grade_categories', $course_category)) { return false; @@ -83,7 +83,7 @@ function upgrade_18_gradebook($courseid) { $category->fullname = addslashes($oldcat->name); $category->parent = $course_category->id; $category->droplow = $oldcat->drop_x_lowest; - $category->aggregation = GRADE_AGGREGATE_MEAN_ALL; + $category->aggregation = GRADE_AGGREGATE_MEAN; $category->timemodified = $category->timecreated = time(); if (!$category->id = insert_record('grade_categories', $category)) { return false; @@ -115,7 +115,7 @@ function upgrade_18_gradebook($courseid) { } } - $course_category->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN_ALL; + $course_category->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN; update_record('grade_categories', $course_category); } unset($oldcats); @@ -149,8 +149,8 @@ function upgrade_18_gradebook($courseid) { $newitems[$olditem->id] = $item; - if ($olditem->extra_credit and $categories[$olditem->category]->aggregation != GRADE_AGGREGATE_EXTRACREDIT_MEAN_ALL) { - $categories[$olditem->category]->aggregation = GRADE_AGGREGATE_EXTRACREDIT_MEAN_ALL; + if ($olditem->extra_credit and $categories[$olditem->category]->aggregation != GRADE_AGGREGATE_EXTRACREDIT_MEAN) { + $categories[$olditem->category]->aggregation = GRADE_AGGREGATE_EXTRACREDIT_MEAN; update_record('grade_categories', $categories[$olditem->category]); } } diff --git a/lib/grade/grade_category.php b/lib/grade/grade_category.php index 3573295aa73..926e42b9a52 100644 --- a/lib/grade/grade_category.php +++ b/lib/grade/grade_category.php @@ -63,7 +63,7 @@ class grade_category extends grade_object { var $depth = 0; /** - * Shows the hierarchical path for this category as /1/2/3 (like course_categories), the last number being + * Shows the hierarchical path for this category as /1/2/3/ (like course_categories), the last number being * this category's autoincrement ID number. * @var string $path */ @@ -79,7 +79,7 @@ class grade_category extends grade_object { * A constant pointing to one of the predefined aggregation strategies (none, mean, median, sum etc) . * @var int $aggregation */ - var $aggregation = GRADE_AGGREGATE_MEAN_ALL; + var $aggregation = GRADE_AGGREGATE_MEAN; /** * Keep only the X highest items. @@ -93,12 +93,24 @@ class grade_category extends grade_object { */ var $droplow = 0; + /** + * Aggregate only graded items + * @var int $aggregateonlygraded + */ + var $aggregateonlygraded = 0; + /** * Aggregate outcomes together with normal items - * @$aggregateoutcomes + * @var int $aggregateoutcomes */ var $aggregateoutcomes = 0; + /** + * Ignore subcategories when aggregating + * @var int $aggregatesubcats + */ + var $aggregatesubcats = 0; + /** * Array of grade_items or grade_categories nested exactly 1 level below this category * @var array $children @@ -136,10 +148,10 @@ class grade_category extends grade_object { */ function build_path($grade_category) { if (empty($grade_category->parent)) { - return '/'.$grade_category->id; + return '/'.$grade_category->id.'/'; } else { $parent = get_record('grade_categories', 'id', $grade_category->parent); - return grade_category::build_path($parent).'/'.$grade_category->id; + return grade_category::build_path($parent).$grade_category->id.'/'; } } @@ -177,7 +189,7 @@ class grade_category extends grade_object { // force recalculation of path; if (empty($this->path)) { $this->path = grade_category::build_path($this); - $this->depth = substr_count($this->path, '/'); + $this->depth = substr_count($this->path, '/') - 1; } @@ -287,7 +299,7 @@ class grade_category extends grade_object { $this->fullname = get_string('coursegradecategory', 'grades'); $this->path = null; $this->parent = null; - $this->aggregate = GRADE_AGGREGATE_MEAN_ALL; + $this->aggregate = GRADE_AGGREGATE_MEAN; if (!parent::insert('system')) { debugging("Could not insert this category: " . print_r($this, true)); @@ -314,12 +326,14 @@ class grade_category extends grade_object { $db_item = grade_category::fetch(array('id'=>$this->id)); - $aggregationdiff = $db_item->aggregation != $this->aggregation; - $keephighdiff = $db_item->keephigh != $this->keephigh; - $droplowdiff = $db_item->droplow != $this->droplow; - $aggoutcomesdiff = $db_item->aggregateoutcomes != $this->aggregateoutcomes; + $aggregationdiff = $db_item->aggregation != $this->aggregation; + $keephighdiff = $db_item->keephigh != $this->keephigh; + $droplowdiff = $db_item->droplow != $this->droplow; + $aggonlygrddiff = $db_item->aggregateonlygraded != $this->aggregateonlygraded; + $aggoutcomesdiff = $db_item->aggregateoutcomes != $this->aggregateoutcomes; + $aggsubcatsdiff = $db_item->aggregatesubcats != $this->aggregatesubcats; - return ($aggregationdiff || $keephighdiff || $droplowdiff || $aggoutcomesdiff); + return ($aggregationdiff || $keephighdiff || $droplowdiff || $aggonlygrddiff || $aggoutcomesdiff || $aggsubcatsdiff); } /** @@ -475,20 +489,12 @@ class grade_category extends grade_object { } // use min grade if grade missing for these types - switch ($this->aggregation) { - case GRADE_AGGREGATE_MEAN_ALL: - case GRADE_AGGREGATE_MEDIAN_ALL: - case GRADE_AGGREGATE_MIN_ALL: - case GRADE_AGGREGATE_MAX_ALL: - case GRADE_AGGREGATE_MODE_ALL: - case GRADE_AGGREGATE_WEIGHTED_MEAN_ALL: - case GRADE_AGGREGATE_EXTRACREDIT_MEAN_ALL: - foreach($items as $itemid=>$value) { - if (!isset($grade_values[$itemid]) and !in_array($itemid, $excluded)) { - $grade_values[$itemid] = 0; - } + if (!$this->aggregateonlygraded) { + foreach($items as $itemid=>$value) { + if (!isset($grade_values[$itemid]) and !in_array($itemid, $excluded)) { + $grade_values[$itemid] = 0; } - break; + } } // limit and sort @@ -508,8 +514,7 @@ class grade_category extends grade_object { /// start the aggregation switch ($this->aggregation) { - case GRADE_AGGREGATE_MEDIAN_ALL: // Middle point value in the set: ignores frequencies - case GRADE_AGGREGATE_MEDIAN_GRADED: + case GRADE_AGGREGATE_MEDIAN: // Middle point value in the set: ignores frequencies $num = count($grade_values); $grades = array_values($grade_values); if ($num % 2 == 0) { @@ -519,18 +524,15 @@ class grade_category extends grade_object { } break; - case GRADE_AGGREGATE_MIN_ALL: - case GRADE_AGGREGATE_MIN_GRADED: + case GRADE_AGGREGATE_MIN: $agg_grade = reset($grade_values); break; - case GRADE_AGGREGATE_MAX_ALL: - case GRADE_AGGREGATE_MAX_GRADED: + case GRADE_AGGREGATE_MAX: $agg_grade = array_pop($grade_values); break; - case GRADE_AGGREGATE_MODE_ALL: // the most common value, average used if multimode - case GRADE_AGGREGATE_MODE_GRADED: + case GRADE_AGGREGATE_MODE: // the most common value, average used if multimode $freq = array_count_values($grade_values); arsort($freq); // sort by frequency keeping keys $top = reset($freq); // highest frequency count @@ -539,8 +541,7 @@ class grade_category extends grade_object { $agg_grade = reset($modes); break; - case GRADE_AGGREGATE_WEIGHTED_MEAN_GRADED: // Weighted average of all existing final grades - case GRADE_AGGREGATE_WEIGHTED_MEAN_ALL: + case GRADE_AGGREGATE_WEIGHTED_MEAN: // Weighted average of all existing final grades $weightsum = 0; $sum = 0; foreach($grade_values as $itemid=>$grade_value) { @@ -557,8 +558,7 @@ class grade_category extends grade_object { } break; - case GRADE_AGGREGATE_EXTRACREDIT_MEAN_ALL: // special average - case GRADE_AGGREGATE_EXTRACREDIT_MEAN_GRADED: + case GRADE_AGGREGATE_EXTRACREDIT_MEAN: // special average $num = 0; $sum = 0; foreach($grade_values as $itemid=>$grade_value) { @@ -576,8 +576,7 @@ class grade_category extends grade_object { } break; - case GRADE_AGGREGATE_MEAN_ALL: // Arithmetic average of all grade items including even NULLs; NULL grade counted as minimum - case GRADE_AGGREGATE_MEAN_GRADED: // Arithmetic average of all final grades, unfinished are not calculated + case GRADE_AGGREGATE_MEAN: // Arithmetic average of all grade items (if ungraded aggregated, NULL counted as minimum) default: $num = count($grade_values); $sum = array_sum($grade_values); @@ -638,10 +637,8 @@ class grade_category extends grade_object { * @return boolean true if coeficient used */ function is_aggregationcoef_used() { - return ($this->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN_ALL - or $this->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN_GRADED - or $this->aggregation == GRADE_AGGREGATE_EXTRACREDIT_MEAN_ALL - or $this->aggregation == GRADE_AGGREGATE_EXTRACREDIT_MEAN_GRADED); + return ($this->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN + or $this->aggregation == GRADE_AGGREGATE_EXTRACREDIT_MEAN); } diff --git a/lib/grade/grade_item.php b/lib/grade/grade_item.php index 038f96b1952..bb2548dd212 100644 --- a/lib/grade/grade_item.php +++ b/lib/grade/grade_item.php @@ -1152,20 +1152,33 @@ class grade_item extends grade_object { $outcomes_sql = "AND gi.outcomeid IS NULL"; } - $sql = "SELECT gi.id - FROM {$CFG->prefix}grade_items gi - WHERE gi.categoryid = {$grade_category->id} - AND (gi.gradetype = ".GRADE_TYPE_VALUE." OR gi.gradetype = ".GRADE_TYPE_SCALE.") - $outcomes_sql + if ($grade_category->aggregatesubcats) { + // return all children excluding category items + $sql = "SELECT gi.id + FROM {$CFG->prefix}grade_items gi + WHERE (gi.gradetype = ".GRADE_TYPE_VALUE." OR gi.gradetype = ".GRADE_TYPE_SCALE.") + $outcomes_sql + AND gi.categoryid IN ( + SELECT gc.id + FROM {$CFG->prefix}grade_categories gc + WHERE gc.path LIKE '%/{$grade_category->id}/%')"; - UNION - - SELECT gi.id - FROM {$CFG->prefix}grade_items gi, {$CFG->prefix}grade_categories gc - WHERE (gi.itemtype = 'category' OR gi.itemtype = 'course') AND gi.iteminstance=gc.id - AND gc.parent = {$grade_category->id} - AND (gi.gradetype = ".GRADE_TYPE_VALUE." OR gi.gradetype = ".GRADE_TYPE_SCALE.") - $outcomes_sql"; + } else { + $sql = "SELECT gi.id + FROM {$CFG->prefix}grade_items gi + WHERE gi.categoryid = {$grade_category->id} + AND (gi.gradetype = ".GRADE_TYPE_VALUE." OR gi.gradetype = ".GRADE_TYPE_SCALE.") + $outcomes_sql + + UNION + + SELECT gi.id + FROM {$CFG->prefix}grade_items gi, {$CFG->prefix}grade_categories gc + WHERE (gi.itemtype = 'category' OR gi.itemtype = 'course') AND gi.iteminstance=gc.id + AND gc.parent = {$grade_category->id} + AND (gi.gradetype = ".GRADE_TYPE_VALUE." OR gi.gradetype = ".GRADE_TYPE_SCALE.") + $outcomes_sql"; + } if ($children = get_records_sql($sql)) { return array_keys($children); diff --git a/lib/grade/simpletest/testgradecategory.php b/lib/grade/simpletest/testgradecategory.php index c5b08c526f4..5a1df76d4a4 100755 --- a/lib/grade/simpletest/testgradecategory.php +++ b/lib/grade/simpletest/testgradecategory.php @@ -53,7 +53,7 @@ class grade_category_test extends grade_test { $this->assertEqual($params->courseid, $grade_category->courseid); $this->assertEqual($params->fullname, $grade_category->fullname); $this->assertEqual(2, $grade_category->depth); - $this->assertEqual("/$course_category->id/$grade_category->id", $grade_category->path); + $this->assertEqual("/$course_category->id/$grade_category->id/", $grade_category->path); $parentpath = $grade_category->path; // Test a child category @@ -63,7 +63,7 @@ class grade_category_test extends grade_test { $grade_category->insert(); $this->assertEqual(3, $grade_category->depth); - $this->assertEqual("$parentpath/$grade_category->id", $grade_category->path); + $this->assertEqual($parentpath.$grade_category->id."/", $grade_category->path); $parentpath = $grade_category->path; // Test a third depth category @@ -72,7 +72,7 @@ class grade_category_test extends grade_test { $grade_category = new grade_category($params, false); $grade_category->insert(); $this->assertEqual(4, $grade_category->depth); - $this->assertEqual("$parentpath/$grade_category->id", $grade_category->path); + $this->assertEqual($parentpath.$grade_category->id."/", $grade_category->path); } function test_grade_category_build_path() { @@ -106,7 +106,7 @@ class grade_category_test extends grade_test { $grade_category->fullname = 'Updated info for this unittest grade_category'; $grade_category->path = null; // path must be recalculated if missing $grade_category->depth = null; - $grade_category->aggregation = GRADE_AGGREGATE_MAX_ALL; // should force regrading + $grade_category->aggregation = GRADE_AGGREGATE_MAX; // should force regrading $grade_item = $grade_category->get_grade_item(); $this->assertEqual(0, $grade_item->needsupdate); @@ -142,7 +142,8 @@ class grade_category_test extends grade_test { $grade_category->fullname = 'unittestcategory4'; $grade_category->courseid = $this->courseid; - $grade_category->aggregation = GRADE_AGGREGATE_MEAN_GRADED; + $grade_category->aggregation = GRADE_AGGREGATE_MEAN; + $grade_category->aggregateonlygraded = 1; $grade_category->keephigh = 100; $grade_category->droplow = 10; $grade_category->hidden = 0; @@ -150,7 +151,7 @@ class grade_category_test extends grade_test { $grade_category->insert(); - $this->assertEqual('/'.$course_category->id.'/'.$this->grade_categories[0]->id.'/'.$grade_category->id, $grade_category->path); + $this->assertEqual('/'.$course_category->id.'/'.$this->grade_categories[0]->id.'/'.$grade_category->id.'/', $grade_category->path); $this->assertEqual(3, $grade_category->depth); $last_grade_category = end($this->grade_categories); @@ -171,9 +172,9 @@ class grade_category_test extends grade_test { $id = $grade_category->insert_course_category($this->courseid); $this->assertNotNull($id); $this->assertEqual('course grade category', $grade_category->fullname); - $this->assertEqual(GRADE_AGGREGATE_MEAN_ALL, $grade_category->aggregate); - $this->assertEqual("/$id", $grade_category->path); - $this->assertEqual($id, $grade_category->depth); + $this->assertEqual(GRADE_AGGREGATE_MEAN, $grade_category->aggregate); + $this->assertEqual("/$id/", $grade_category->path); + $this->assertEqual(1, $grade_category->depth); $this->assertNull($grade_category->parent); } @@ -183,7 +184,7 @@ class grade_category_test extends grade_test { $this->assertFalse($grade_category->qualifies_for_regrading()); - $grade_category->aggregation = GRADE_AGGREGATE_MAX_ALL; + $grade_category->aggregation = GRADE_AGGREGATE_MAX; $this->assertTrue($grade_category->qualifies_for_regrading()); $grade_category = new grade_category($this->grade_categories[0]); diff --git a/lib/gradelib.php b/lib/gradelib.php index d3acbcb92c1..de0a75b642d 100644 --- a/lib/gradelib.php +++ b/lib/gradelib.php @@ -33,20 +33,13 @@ */ // category aggregation types -define('GRADE_AGGREGATE_MEAN_ALL', 0); -define('GRADE_AGGREGATE_MEAN_GRADED', 1); -define('GRADE_AGGREGATE_MEDIAN_ALL', 2); -define('GRADE_AGGREGATE_MEDIAN_GRADED', 3); -define('GRADE_AGGREGATE_MIN_ALL', 4); -define('GRADE_AGGREGATE_MIN_GRADED', 5); -define('GRADE_AGGREGATE_MAX_ALL', 6); -define('GRADE_AGGREGATE_MAX_GRADED', 7); -define('GRADE_AGGREGATE_MODE_ALL', 8); -define('GRADE_AGGREGATE_MODE_GRADED', 9); -define('GRADE_AGGREGATE_WEIGHTED_MEAN_ALL', 10); -define('GRADE_AGGREGATE_WEIGHTED_MEAN_GRADED', 11); -define('GRADE_AGGREGATE_EXTRACREDIT_MEAN_ALL', 12); -define('GRADE_AGGREGATE_EXTRACREDIT_MEAN_GRADED', 13); +define('GRADE_AGGREGATE_MEAN', 0); +define('GRADE_AGGREGATE_MEDIAN', 2); +define('GRADE_AGGREGATE_MIN', 4); +define('GRADE_AGGREGATE_MAX', 6); +define('GRADE_AGGREGATE_MODE', 8); +define('GRADE_AGGREGATE_WEIGHTED_MEAN', 10); +define('GRADE_AGGREGATE_EXTRACREDIT_MEAN', 12); // grade types define('GRADE_TYPE_NONE', 0); @@ -77,6 +70,8 @@ define('GRADE_REPORT_GRADE_DISPLAY_TYPE_LETTER', 2); define('GRADE_REPORT_PREFERENCE_DEFAULT', 'default'); define('GRADE_REPORT_PREFERENCE_INHERIT', 'inherit'); define('GRADE_REPORT_PREFERENCE_UNUSED', -1); +define('GRADE_REPORT_MEAN_ALL', 0); +define('GRADE_REPORT_MEAN_GRADED', 1); require_once($CFG->libdir . '/grade/grade_category.php'); require_once($CFG->libdir . '/grade/grade_item.php'); diff --git a/lib/simpletest/fixtures/gradetest.php b/lib/simpletest/fixtures/gradetest.php index 2860e20a59e..efbb20793ee 100644 --- a/lib/simpletest/fixtures/gradetest.php +++ b/lib/simpletest/fixtures/gradetest.php @@ -154,6 +154,9 @@ class grade_test extends UnitTestCase { $table->addFieldInfo('aggregation', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, null, '0'); $table->addFieldInfo('keephigh', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, null, '0'); $table->addFieldInfo('droplow', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, null, '0'); + $table->addFieldInfo('aggregateonlygraded', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); + $table->addFieldInfo('aggregateoutcomes', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); + $table->addFieldInfo('aggregatesubcats', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); $table->addFieldInfo('timecreated', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); $table->addFieldInfo('timemodified', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); @@ -368,6 +371,9 @@ class grade_test extends UnitTestCase { $table->addFieldInfo('aggregation', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, null, '0'); $table->addFieldInfo('keephigh', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, null, '0'); $table->addFieldInfo('droplow', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, null, '0'); + $table->addFieldInfo('aggregateonlygraded', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); + $table->addFieldInfo('aggregateoutcomes', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); + $table->addFieldInfo('aggregatesubcats', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0'); /// Adding keys to table grade_categories_history $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); @@ -647,7 +653,8 @@ class grade_test extends UnitTestCase { $grade_category->fullname = 'unittestcategory1'; $grade_category->courseid = $this->courseid; - $grade_category->aggregation = GRADE_AGGREGATE_MEAN_GRADED; + $grade_category->aggregation = GRADE_AGGREGATE_MEAN; + $grade_category->aggregateonlygraded = 1; $grade_category->keephigh = 0; $grade_category->droplow = 0; $grade_category->parent = $course_category->id; @@ -656,7 +663,7 @@ class grade_test extends UnitTestCase { $grade_category->depth = 2; if ($grade_category->id = insert_record('grade_categories', $grade_category)) { - $grade_category->path = '/'.$course_category->id.'/'.$grade_category->id; + $grade_category->path = '/'.$course_category->id.'/'.$grade_category->id.'/'; update_record('grade_categories', $grade_category); $this->grade_categories[0] = $grade_category; } @@ -665,7 +672,8 @@ class grade_test extends UnitTestCase { $grade_category->fullname = 'unittestcategory2'; $grade_category->courseid = $this->courseid; - $grade_category->aggregation = GRADE_AGGREGATE_MEAN_GRADED; + $grade_category->aggregation = GRADE_AGGREGATE_MEAN; + $grade_category->aggregateonlygraded = 1; $grade_category->keephigh = 0; $grade_category->droplow = 0; $grade_category->parent = $this->grade_categories[0]->id; @@ -674,7 +682,7 @@ class grade_test extends UnitTestCase { $grade_category->depth = 3; if ($grade_category->id = insert_record('grade_categories', $grade_category)) { - $grade_category->path = $this->grade_categories[0]->path.'/'.$grade_category->id; + $grade_category->path = $this->grade_categories[0]->path.$grade_category->id.'/'; update_record('grade_categories', $grade_category); $this->grade_categories[1] = $grade_category; } @@ -683,7 +691,8 @@ class grade_test extends UnitTestCase { $grade_category->fullname = 'unittestcategory3'; $grade_category->courseid = $this->courseid; - $grade_category->aggregation = GRADE_AGGREGATE_MEAN_GRADED; + $grade_category->aggregation = GRADE_AGGREGATE_MEAN; + $grade_category->aggregateonlygraded = 1; $grade_category->keephigh = 0; $grade_category->droplow = 0; $grade_category->parent = $this->grade_categories[0]->id; @@ -692,7 +701,7 @@ class grade_test extends UnitTestCase { $grade_category->depth = 3; if ($grade_category->id = insert_record('grade_categories', $grade_category)) { - $grade_category->path = $this->grade_categories[0]->path.'/'.$grade_category->id; + $grade_category->path = $this->grade_categories[0]->path.$grade_category->id.'/'; update_record('grade_categories', $grade_category); $this->grade_categories[2] = $grade_category; } @@ -703,7 +712,8 @@ class grade_test extends UnitTestCase { $grade_category->fullname = 'level1category'; $grade_category->courseid = $this->courseid; - $grade_category->aggregation = GRADE_AGGREGATE_MEAN_GRADED; + $grade_category->aggregation = GRADE_AGGREGATE_MEAN; + $grade_category->aggregateonlygraded = 1; $grade_category->keephigh = 0; $grade_category->droplow = 0; $grade_category->parent = $course_category->id; @@ -712,7 +722,7 @@ class grade_test extends UnitTestCase { $grade_category->depth = 2; if ($grade_category->id = insert_record('grade_categories', $grade_category)) { - $grade_category->path = '/'.$course_category->id.'/'.$grade_category->id; + $grade_category->path = '/'.$course_category->id.'/'.$grade_category->id.'/'; update_record('grade_categories', $grade_category); $this->grade_categories[3] = $grade_category; } diff --git a/version.php b/version.php index 93bcc7777d4..482068a8f6b 100644 --- a/version.php +++ b/version.php @@ -6,7 +6,7 @@ // This is compared against the values stored in the database to determine // whether upgrades should be performed (see lib/db/*.php) - $version = 2007083101; // YYYYMMDD = date + $version = 2007090503; // YYYYMMDD = date // XY = increments within a single day $release = '1.9 Beta +'; // Human-friendly version name