This commit is contained in:
skodak 2007-10-19 08:51:52 +00:00
parent deb2988f39
commit d297269d79
13 changed files with 284 additions and 162 deletions

View file

@ -521,7 +521,38 @@ class grade_category extends grade_object {
return;
}
/// start the aggregation
// do the maths
$agg_grade = $this->aggregate_values($grade_values, $items);
/// prepare update of new raw grade
$grade->rawgrademin = $this->grade_item->grademin;
$grade->rawgrademax = $this->grade_item->grademax;
$grade->rawscaleid = $this->grade_item->scaleid;
$grade->rawgrade = null; // categories do not use raw grades
// recalculate the rawgrade back to requested range
$finalgrade = grade_grade::standardise_score($agg_grade, 0, 1, $this->grade_item->grademin, $this->grade_item->grademax);
if (!is_null($finalgrade)) {
$grade->finalgrade = bounded_number($this->grade_item->grademin, $finalgrade, $this->grade_item->grademax);
} else {
$grade->finalgrade = $finalgrade;
}
// update in db if changed
if ( $grade->finalgrade !== $oldgrade->finalgrade
or $grade->rawgrade !== $oldgrade->rawgrade
or $grade->rawgrademin !== $oldgrade->rawgrademin
or $grade->rawgrademax !== $oldgrade->rawgrademax
or $grade->rawscaleid !== $oldgrade->rawscaleid) {
$grade->update('system');
}
return;
}
function aggregate_values($grade_values, $items) {
switch ($this->aggregation) {
case GRADE_AGGREGATE_MEDIAN: // Middle point value in the set: ignores frequencies
$num = count($grade_values);
@ -593,34 +624,8 @@ class grade_category extends grade_object {
break;
}
/// prepare update of new raw grade
$grade->rawgrademin = $this->grade_item->grademin;
$grade->rawgrademax = $this->grade_item->grademax;
$grade->rawscaleid = $this->grade_item->scaleid;
$grade->rawgrade = null; // categories do not use raw grades
// recalculate the rawgrade back to requested range
$finalgrade = grade_grade::standardise_score($agg_grade, 0, 1, $this->grade_item->grademin, $this->grade_item->grademax);
if (!is_null($finalgrade)) {
$grade->finalgrade = bounded_number($this->grade_item->grademin, $finalgrade, $this->grade_item->grademax);
} else {
$grade->finalgrade = $finalgrade;
}
// update in db if changed
if ( $grade->finalgrade !== $oldgrade->finalgrade
or $grade->rawgrade !== $oldgrade->rawgrade
or $grade->rawgrademin !== $oldgrade->rawgrademin
or $grade->rawgrademax !== $oldgrade->rawgrademax
or $grade->rawscaleid !== $oldgrade->rawscaleid) {
$grade->update('system');
}
return;
return $agg_grade;
}
/**
* Given an array of grade values (numerical indices), applies droplow or keephigh
* rules to limit the final array.

View file

@ -142,7 +142,7 @@ class grade_grade extends grade_object {
* Returns array of grades for given grade_item+users.
* @param object $grade_item
* @param array $userids
* @param bool $include_missing include grades taht do not exist yet
* @param bool $include_missing include grades that do not exist yet
* @return array userid=>grade_grade array
*/
function fetch_users_grades($grade_item, $userids, $include_missing=true) {
@ -475,45 +475,136 @@ class grade_grade extends grade_object {
/**
* Return array of grade item ids that are either hidden or indirectly depend
* on hidden grades, excluded grades are not returned.
* THIS IS A REALLY BIG HACK! to be replaced by conditional aggregation of hidden grades in 2.0
*
* @static
* @param array $grades all course grades of one user, & used for better internal caching
* @param array $items $grade_items array of grade items, & used for better internal caching
* @return array
*/
function get_hiding_affected(&$grade_grades, &$grade_items) {
global $CFG;
if (count($grade_grades) !== count($grade_items)) {
error("Incorrent size of arrays in params of grade_grade::get_hiding_affected()!");
}
$dependson = array();
$todo = array();
$unknown = array(); // can not find altered
$altered = array(); // altered grades
foreach($grade_items as $key=>$unused) {
$grade_item =& $grade_items[$key]; // reference for improved caching inside grade_item
$dependson[$grade_item->id] = $grade_item->depends_on();
$dependson[$grade_items[$key]->id] = $grade_items[$key]->depends_on();
}
$todo = array();
$hiding = array();
$hiddenfound = false;
foreach($grade_grades as $grade_grade) {
if ($grade_grade->is_hidden() and !$grade_grade->is_excluded() and !is_null($grade_grade->finalgrade)) {
$hiding[] = $grade_grade->itemid;
} else {
if ($grade_grade->is_excluded()) {
//nothing to do, aggregation is ok
} else if ($grade_grade->is_hidden()) {
$hiddenfound = true;
// hidden null grade does not affect the aggregation
if (!is_null($grade_grade->finalgrade)) {
$altered[$grade_grade->itemid] = null;
}
} else if (!empty($dependson[$grade_grade->itemid])) {
$todo[] = $grade_grade->itemid;
}
}
if (!$hiddenfound) {
return array('unknown'=>array(), 'altered'=>array());
}
$max = count($grade_items);
$max = count($todo);
for($i=0; $i<$max; $i++) {
$found = false;
foreach($todo as $key=>$do) {
if (empty($dependson[$do])) {
unset($todo[$key]);
continue;
} else if (array_intersect($dependson[$do], $hiding)) {
if (array_intersect($dependson[$do], $unknown)) {
// this item depends on hidden grade indirectly
$hiding[] = $do;
$unknown[$do] = $do;
unset($todo[$key]);
$found = true;
continue;
} else if (!array_intersect($dependson[$do], $todo)) {
if (!array_intersect($dependson[$do], array_keys($altered))) {
// hiding does not affect this grade
unset($todo[$key]);
$found = true;
continue;
} else {
// depends on altered grades - we should try to recalculate if possible
if ($grade_items[$do]->is_calculated() or (!$grade_items[$do]->is_category_item() and !$grade_items[$do]->is_course_item())) {
$unknown[$do] = $do;
unset($todo[$key]);
$found = true;
continue;
} else {
$grade_category = $grade_items[$do]->load_item_category();
$values = array();
foreach ($dependson[$do] as $itemid) {
if (array_key_exists($itemid, $altered)) {
$values[$itemid] = $altered[$itemid];
} else {
$values[$itemid] = $grade_grades[$itemid]->finalgrade;
}
}
if ($CFG->grade_aggregateonlygraded != -1) {
$grade_category->aggregateonlygraded = $CFG->grade_aggregateonlygraded;
}
if ($grade_category->aggregateonlygraded) {
foreach ($values as $itemid=>$value) {
if (is_null($value)) {
unset($values[$itemid]);
}
}
} else {
foreach ($values as $itemid=>$value) {
if (is_null($value)) {
$values[$itemid] = $grade_items[$itemid]->grademin;
}
}
}
foreach ($values as $itemid=>$value) {
if ($grade_grades[$itemid]->is_excluded()) {
unset($values[$itemid]);
continue;
}
$values[$itemid] = grade_grade::standardise_score($value, $grade_items[$itemid]->grademin, $grade_items[$itemid]->grademax, 0, 1);
}
// limit and sort
$grade_category->apply_limit_rules($values);
asort($values, SORT_NUMERIC);
// let's see we have still enough grades to do any statistics
if (count($values) == 0) {
// not enough attempts yet
$altered[$do] = null;
unset($todo[$key]);
$found = true;
continue;
}
$agg_grade = $grade_category->aggregate_values($values, $grade_items);
// recalculate the rawgrade back to requested range
$finalgrade = grade_grade::standardise_score($agg_grade, 0, 1, $grade_items[$itemid]->grademin, $grade_items[$itemid]->grademax);
if (!is_null($finalgrade)) {
$finalgrade = bounded_number($grade_items[$itemid]->grademin, $finalgrade, $grade_items[$itemid]->grademax);
}
$altered[$do] = $finalgrade;
unset($todo[$key]);
$found = true;
continue;
}
}
}
}
if (!$found) {
@ -521,7 +612,7 @@ class grade_grade extends grade_object {
}
}
return $hiding;
return array('unknown'=>$unknown, 'altered'=>$altered);
}
}
?>