Counting any grade not 0 as 1 for totals calculation

Counting any grade not 0 as 1 for totals calculation

by Mike Worth -
Number of replies: 2
I am administering moodle for a college; it is being used to track homework completion.

I want the course totals to show the percentage(amount complete in x/y style would be perfect but not essential) of homeworks completed. In order for this to work I want some way for the course total to take a sort-of weighted mean of all the grades but count anything >0 as a 1 (so that 0 is not done and - is excused)

Anyone managed this before?

Thanks,
Mike
In reply to Mike Worth

Re: Counting any grade not 0 as 1 for totals calculation

by Mike Worth -
I've managed to do this with a new type of aggregaion.

I changed lib/grade/grade_category.php around line 508 to be:


/// sum is a special aggregation types - it adjusts the min max, does not use relative values
if ($this->aggregation == GRADE_AGGREGATE_SUM) {
$this->sum_grades($grade, $oldfinalgrade, $items, $grade_values, $excluded);
return;
}

/// outof is a special aggregation types - it does not use relative values
if ($this->aggregation == GRADE_AGGREGATE_OUTOF) {
$this->outof_grades($grade, $oldfinalgrade, $items, $grade_values, $excluded);
return;
}

(the first bit is already there)
and the following at about 765 (after sum_grades):

/**
* internal function for category grades outof calculation
*
* @param object $grade
* @param int $userid
* @param float $oldfinalgrade
* @param array $items
* @param array $grade_values
* @param bool $excluded
* @return boolean (just plain return;)
*/
function outof_grades(&$grade, $oldfinalgrade, $items, $grade_values, $excluded) {

$completed=0;

// ungraded and exluded items are not used in aggregation
foreach ($grade_values as $itemid=>$v) {
if (is_null($v)) {
unset($grade_values[$itemid]);
} else if (in_array($itemid, $excluded)) {
unset($grade_values[$itemid]);
}
}
foreach ($items as $item){
//have they done this piece of work?
if ($item->gradetype == GRADE_TYPE_VALUE and $grade_values[$item->id]>0){
$completed+=1;
}elseif ($item->gradetype == GRADE_TYPE_SCALE and $grade_values[$item->id]>1){
$completed+=1;
}
}


$max = count($grade_values);

if ($this->grade_item->grademax != $max or $this->grade_item->grademin != 0 or $this->grade_item->gradetype != GRADE_TYPE_VALUE){
$this->grade_item->grademax = 1;
$this->grade_item->grademin = 0;
$this->grade_item->gradetype = GRADE_TYPE_VALUE;
$this->grade_item->update('aggregation');
}

$this->apply_limit_rules($grade_values);


$outof=$completed / $max;

$grade->finalgrade = $outof;

// update in db if changed
if (grade_floats_different($grade->finalgrade, $oldfinalgrade)) {
$grade->update('aggregation');
}

return;
}

I also had to add a line for GRADE_AGGREGATE_OUTOF to admin/settings/grades.php,lib/grade/constants.php,/grade/edit/tree/category_form.php and an entry into the langfile.

Now I just have one little problem: although I've set needsupdate=1 for everything it's not actually updating until someone looks at the grader report- the course totals are displayed on other pages, is there a way to actually update them all automatically?

Mike
In reply to Mike Worth

Re: Counting any grade not 0 as 1 for totals calculation

by Mike Worth -
I've managed to recalculate all the grades- wrote a little script:

<?php

require_once('/usr/share/moodle/config.php');
require_once('/usr/share/moodle/lib/gradelib.php');

$courses=get_records('course');

foreach ($courses as $course){
if(grade_regrade_final_grades($course->id))echo "updated grades for $course->shortname<br>";
}

?>