mirror of
https://github.com/moodle/moodle.git
synced 2025-08-05 08:56:36 +02:00
This commit is contained in:
parent
deb2988f39
commit
d297269d79
13 changed files with 284 additions and 162 deletions
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue