aggregation improvements; fixed aggregation of course category when changing type; old gradebook upgrade wip (untested)

This commit is contained in:
skodak
2007-07-21 10:09:57 +00:00
parent 9acbd7269c
commit eacd3700f4
4 changed files with 130 additions and 106 deletions
+8 -4
View File
@@ -13,10 +13,14 @@ class edit_category_form extends moodleform {
$options = array(GRADE_AGGREGATE_MEAN_ALL =>get_string('aggregatemeanall', 'grades'),
GRADE_AGGREGATE_MEAN_GRADED =>get_string('aggregatemeangraded', '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_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'),
+8 -4
View File
@@ -10,11 +10,15 @@ $string['additem'] = 'Add Grade 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['aggregatemedian'] = 'Median of non-empty grades';
$string['aggregatemeangraded'] = 'Mean of non-empty grades';
$string['aggregatemin'] = 'Smallest grade';
$string['aggregatemax'] = 'Highest grade';
$string['aggregatemode'] = 'Mode 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 non-empty grades of all grades';
$string['aggregatemodegraded'] = 'Mode of non-empty grades';
$string['aggregateweightedmeanall'] = 'Weighted mean of all grades';
$string['aggregateweightedmeangraded'] = 'Weighted mean of non-empty grades';
$string['aggregation'] = 'Aggregation';
+36 -55
View File
@@ -433,7 +433,24 @@ class grade_category extends grade_object {
$grade_values[$k] = grade_grade::standardise_score($v, $items[$k]->grademin, $items[$k]->grademax, 0, 1);
}
//limit and sort
// 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])) {
$grade_values[$itemid] = 0;
}
}
break;
}
// limit and sort
$this->apply_limit_rules($grade_values);
asort($grade_values, SORT_NUMERIC);
@@ -450,7 +467,8 @@ class grade_category extends grade_object {
/// start the aggregation
switch ($this->aggregation) {
case GRADE_AGGREGATE_MEDIAN: // Middle point value in the set: ignores frequencies
case GRADE_AGGREGATE_MEDIAN_ALL: // Middle point value in the set: ignores frequencies
case GRADE_AGGREGATE_MEDIAN_GRADED:
$num = count($grade_values);
$grades = array_values($grade_values);
if ($num % 2 == 0) {
@@ -460,15 +478,18 @@ class grade_category extends grade_object {
}
break;
case GRADE_AGGREGATE_MIN:
case GRADE_AGGREGATE_MIN_ALL:
case GRADE_AGGREGATE_MIN_GRADED:
$rawgrade = reset($grade_values);
break;
case GRADE_AGGREGATE_MAX:
case GRADE_AGGREGATE_MAX_ALL:
case GRADE_AGGREGATE_MAX_GRADED:
$rawgrade = array_pop($grade_values);
break;
case GRADE_AGGREGATE_MODE: // the most common value, the highest one if multimode
case GRADE_AGGREGATE_MODE_ALL: // the most common value, average used if multimode
case GRADE_AGGREGATE_MODE_GRADED:
$freq = array_count_values($grade_values);
arsort($freq); // sort by frequency keeping keys
$top = reset($freq); // highest frequency count
@@ -477,33 +498,16 @@ class grade_category extends grade_object {
$rawgrade = reset($modes);
break;
case GRADE_AGGREGATE_WEIGHTED_MEAN_ALL: // Weighted average of all possible final grades
$weightsum = 0;
$sum = 0;
foreach($items as $key=>$value) {
$grade_value = isset($grade_values[$key]) ? $grade_values[$key] : 0;
if ($items[$key]->aggregationcoef <= 0) {
continue;
}
$weightsum += $items[$key]->aggregationcoef;
$sum += $items[$key]->aggregationcoef * $grade_value;
}
if ($weightsum == 0) {
$rawgrade = null;
} else {
$rawgrade = $sum / $weightsum;
}
break;
case GRADE_AGGREGATE_WEIGHTED_MEAN_GRADED: // Weighted average of all existing final grades
case GRADE_AGGREGATE_WEIGHTED_MEAN_ALL:
$weightsum = 0;
$sum = 0;
foreach($grade_values as $key=>$grade_value) {
if ($items[$key]->aggregationcoef <= 0) {
foreach($grade_values as $itemid=>$grade_value) {
if ($items[$itemid]->aggregationcoef <= 0) {
continue;
}
$weightsum += $items[$key]->aggregationcoef;
$sum += $items[$key]->aggregationcoef * $grade_value;
$weightsum += $items[$itemid]->aggregationcoef;
$sum += $items[$itemid]->aggregationcoef * $grade_value;
}
if ($weightsum == 0) {
$rawgrade = null;
@@ -513,33 +517,15 @@ class grade_category extends grade_object {
break;
case GRADE_AGGREGATE_EXTRACREDIT_MEAN_ALL: // special average
case GRADE_AGGREGATE_EXTRACREDIT_MEAN_GRADED:
$num = 0;
$sum = 0;
foreach($items as $key=>$value) {
$grade_value = isset($grade_values[$key]) ? $grade_values[$key] : 0;
if ($items[$key]->aggregationcoef == 0) {
foreach($grade_values as $itemid=>$grade_value) {
if ($items[$itemid]->aggregationcoef == 0) {
$num += 1;
$sum += $grade_value;
} else if ($items[$key]->aggregationcoef > 0) {
$sum += $items[$key]->aggregationcoef * $grade_value;
}
}
if ($num == 0) {
$rawgrade = $sum; // only extra credits or wrong coefs
} else {
$rawgrade = $sum / $num;
}
break;
case GRADE_AGGREGATE_EXTRACREDIT_MEAN_GRADED: // special average
$num = 0;
$sum = 0;
foreach($grade_values as $key=>$grade_value) {
if ($items[$key]->aggregationcoef == 0) {
$num += 1;
$sum += $grade_value;
} else if ($items[$key]->aggregationcoef > 0) {
$sum += $items[$key]->aggregationcoef * $grade_value;
} else if ($items[$itemid]->aggregationcoef > 0) {
$sum += $items[$itemid]->aggregationcoef * $grade_value;
}
}
if ($num == 0) {
@@ -550,11 +536,6 @@ 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
$num = count($items); // you can calculate sum from this one if you multiply it with count($this->depends_on() ;-)
$sum = array_sum($grade_values);
$rawgrade = $sum / $num;
break;
case GRADE_AGGREGATE_MEAN_GRADED: // Arithmetic average of all final grades, unfinished are not calculated
default:
$num = count($grade_values);
+78 -43
View File
@@ -32,31 +32,29 @@
* @package moodlecore
*/
// category aggregation types
define('GRADE_AGGREGATE_MEAN_ALL', 0);
define('GRADE_AGGREGATE_MEAN_GRADED', 1);
define('GRADE_AGGREGATE_MEDIAN', 2);
define('GRADE_AGGREGATE_MIN', 3);
define('GRADE_AGGREGATE_MAX', 4);
define('GRADE_AGGREGATE_MODE', 5);
define('GRADE_AGGREGATE_WEIGHTED_MEAN_ALL', 6);
define('GRADE_AGGREGATE_WEIGHTED_MEAN_GRADED', 7);
define('GRADE_AGGREGATE_EXTRACREDIT_MEAN_ALL', 8);
define('GRADE_AGGREGATE_EXTRACREDIT_MEAN_GRADED', 9);
define('GRADE_CHILDTYPE_ITEM', 0);
define('GRADE_CHILDTYPE_CAT', 1);
define('GRADE_ITEM', 0); // Used to compare class names with CHILDTYPE values
define('GRADE_CATEGORY', 1); // Used to compare class names with CHILDTYPE values
define('GRADE_CATEGORY_CONTRACTED', 0); // The state of a category header in the grader report
define('GRADE_CATEGORY_EXPANDED', 1); // The state of a category header in the grader report
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);
// grade types
define('GRADE_TYPE_NONE', 0);
define('GRADE_TYPE_VALUE', 1);
define('GRADE_TYPE_SCALE', 2);
define('GRADE_TYPE_TEXT', 3);
// grade_update() return status
define('GRADE_UPDATE_OK', 0);
define('GRADE_UPDATE_FAILED', 1);
define('GRADE_UPDATE_MULTIPLE', 2);
@@ -68,11 +66,10 @@ define('GRADE_HISTORY_INSERT', 1);
define('GRADE_HISTORY_UPDATE', 2);
define('GRADE_HISTORY_DELETE', 3);
// Common directories
define('GRADE_EDIT_DIR', $CFG->dirroot . '/grade/edit');
define('GRADE_EDIT_URL', $CFG->wwwroot . '/grade/edit');
// Grader reports
define('GRADE_CATEGORY_CONTRACTED', 0); // The state of a category header in the grader report
define('GRADE_CATEGORY_EXPANDED', 1); // The state of a category header in the grader report
define('GRADE_REPORT_AGGREGATION_POSITION_LEFT', 0);
define('GRADE_REPORT_AGGREGATION_POSITION_RIGHT', 1);
define('GRADE_REPORT_AGGREGATION_VIEW_FULL', 0);
@@ -84,6 +81,10 @@ define('GRADE_REPORT_PREFERENCE_DEFAULT', 'default');
define('GRADE_REPORT_PREFERENCE_INHERIT', 'inherit');
define('GRADE_REPORT_PREFERENCE_UNUSED', -1);
// Common directories
define('GRADE_EDIT_DIR', $CFG->dirroot . '/grade/edit');
define('GRADE_EDIT_URL', $CFG->wwwroot . '/grade/edit');
require_once($CFG->libdir . '/grade/grade_category.php');
require_once($CFG->libdir . '/grade/grade_item.php');
require_once($CFG->libdir . '/grade/grade_grade.php');
@@ -351,7 +352,7 @@ function grade_regrade_final_grades($courseid, $userid=null, $updated_item=null)
if (!empty($updated_item) and $updated_item->id == $gid) {
$grade_items[$gid]->needsupdate = 1;
} else if ($grade_items[$gid]->is_course_item() or $grade_items[$gid]->is_category_item() or $grade_items[$gid]->is_calculated()) {
} else if ($gitem->is_course_item() or $gitem->is_category_item() or $gitem->is_calculated()) {
$grade_items[$gid]->needsupdate = 1;
}
@@ -362,6 +363,7 @@ function grade_regrade_final_grades($courseid, $userid=null, $updated_item=null)
$errors = array();
$finalids = array();
$gids = array_keys($grade_items);
$failed = 0;
while (count($finalids) < count($gids)) { // work until all grades are final or error found
$count = 0;
@@ -399,6 +401,12 @@ function grade_regrade_final_grades($courseid, $userid=null, $updated_item=null)
}
if ($count == 0) {
$failed++;
} else {
$failed = 0;
}
if ($failed > 1) {
foreach($gids as $gid) {
if (in_array($gid, $finalids)) {
continue; // this one is ok
@@ -661,35 +669,54 @@ function grade_get_legacy_grade_item($modinstance, $grademax, $scaleid) {
/**
* This function is used to migrade old date and settings from old gradebook into new grading system.
*
* TODO:
* - category weight not used - we would have to create extra top course grade calculated category
* - exta_credit item flag not used - does not fit all our aggregation types, could be used in SUM only
* @param int $courseid
*/
function grade_oldgradebook_upgrade($courseid) {
function grade_upgrade_oldgradebook($courseid) {
global $CFG;
// regrade everything
grade_force_full_regrading($courseid);
// course grade data
$course_category = grade_category::fetch_course_category($courseid);
$course_item = $course_category->get_grade_item();
// first create all categories if needed
$categories = array();
if ($oldcats = get_records('grade_category', 'courseid', $courseid)) {
$oldcats = get_records('grade_category', 'courseid', $courseid, 'id');
if (empty($oldcats) or count($oldcats) == 1) {
$course_category->aggregation = GRADE_AGGREGATE_MEAN_ALL;
$course_category->update('upgrade');
if ($oldcats) {
$oldcat = reset($oldcats);
$categories[$oldcat->id] =& $course_category;
}
} else {
foreach ($oldcats as $oldcat) {
$newcat = new grade_category(array('courseid'=>$courseid, 'fullname'=>$oldcat->name));
$newcat->droplow = $oldcat->drop_x_lowest;
$newcat->aggregation = GRADE_AGGREGATE_MEAN_GRADED;
$newcat->aggregation = GRADE_AGGREGATE_MEAN_ALL;
if (empty($newcat->id)) {
$newcat->insert();
$newcat->insert('upgrade');
} else {
$newcat->update();
$newcat->update('upgrade');
}
$categories[$oldcat->id] = $newcat;
$categories[$oldcat->id] =& $newcat;
$catitem = $newcat->get_grade_item();
$catitem->gradetype = GRADE_TYPE_VALUE;
$catitem->plusfactor = $oldcat->bonus_points;
$catitem->hidden = $oldcat->hidden;
$catitem->update();
$catitem->gradetype = GRADE_TYPE_VALUE;
$catitem->plusfactor = $oldcat->bonus_points;
$catitem->hidden = $oldcat->hidden;
$catitem->aggregationcoef = $oldcat->weight;
$catitem->update('upgrade');
}
$course_category->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN_ALL;
$course_category->update('upgrade');
}
// get all grade items with mod details
@@ -701,19 +728,27 @@ function grade_oldgradebook_upgrade($courseid) {
if ($olditems = get_records_sql($sql)) {
foreach ($olditems as $olditem) {
$newitem = new grade_item(array('courseid'=>$olditem->courseid, 'itemtype'=>'mod', 'itemmodule'=>$olditem->modname, 'iteminstance'=>$olditem->cminstance, 'itemnumber'=>0));
if (!empty($olditem->category)) {
// we do this low level stuff to get some speedup during upgrade
$newitem->set_parent($categories[$olditem->category]->id);
$newitem->multfactor = $olditem->scale_grade;
$newitem->aggregationcoef = $olditem->extra_credit;
if ($olditem->extra_credit and $categories[$olditem->category]->aggregation != GRADE_AGGREGATE_EXTRACREDIT_MEAN_ALL) {
$categories[$olditem->category]->aggregation = GRADE_AGGREGATE_EXTRACREDIT_MEAN_ALL;
$categories[$olditem->category]->update('upgrade');
}
$newitem->gradetype = GRADE_TYPE_NONE;
$newitem->multfactor = $olditem->scale_grade;
if (empty($newitem->id)) {
$newitem->insert();
$newitem->gradetype = GRADE_TYPE_NONE; // type not known yet
$newitem->insert('upgrade');
} else {
$newitem->update();
$newitem->update('upgrade');
}
if (!empty($olditem->category)) {
$newitem->set_parent($categories[$olditem->category]->id);
}
}
}
// setup up exception handling
}
/**