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

@ -10,8 +10,6 @@ $temp = new admin_settingpage('gradessettings', get_string('gradessettings', 'gr
// enable outcomes checkbox
$temp->add(new admin_setting_configcheckbox('enableoutcomes', get_string('enableoutcomes', 'grades'), get_string('configenableoutcomes', 'grades'), 0, PARAM_INT));
// enable publishing in exports/imports
$temp->add(new admin_setting_configcheckbox('gradepublishing', get_string('gradepublishing', 'grades'), get_string('configgradepublishing', 'grades'), 0, PARAM_INT));
$temp->add(new admin_setting_configselect('grade_aggregationposition', get_string('aggregationposition', 'grades'),
get_string('configaggregationposition', 'grades'), GRADE_REPORT_AGGREGATION_POSITION_LAST,
@ -33,6 +31,11 @@ $temp->add(new admin_setting_configselect('grade_decimalpoints', get_string('dec
'4' => '4',
'5' => '5')));
$temp->add(new admin_setting_configcheckbox('grade_hiddenasdate', get_string('hiddenasdate', 'grades'), get_string('confighiddenasdate', 'grades'), 0, PARAM_INT));
// enable publishing in exports/imports
$temp->add(new admin_setting_configcheckbox('gradepublishing', get_string('gradepublishing', 'grades'), get_string('configgradepublishing', 'grades'), 0, PARAM_INT));
$temp->add(new admin_setting_configselect('grade_export_displaytype', get_string('gradeexportdisplaytype', 'grades'),
get_string('configgradeexportdisplaytype', 'grades'), GRADE_DISPLAY_TYPE_REAL,
array(GRADE_DISPLAY_TYPE_REAL => get_string('real', 'grades'),
@ -51,15 +54,6 @@ $temp->add(new admin_setting_configselect('grade_export_decimalpoints', get_stri
$temp->add(new admin_setting_special_gradeexport());
$ADMIN->add('grades', $temp);
/// Scales and outcomes
$scales = new admin_externalpage('scales', get_string('scales'), $CFG->wwwroot.'/grade/edit/scale/index.php', 'moodle/grade:manage');
$ADMIN->add('grades', $scales);
$outcomes = new admin_externalpage('outcomes', get_string('outcomes', 'grades'), $CFG->wwwroot.'/grade/edit/outcome/index.php', 'moodle/grade:manage');
$ADMIN->add('grades', $outcomes);
$letters = new admin_externalpage('letters', get_string('letters', 'grades'), $CFG->wwwroot.'/grade/edit/letter/edit.php', 'moodle/grade:manageletters');
$ADMIN->add('grades', $letters);
/// Grade category settings
$temp = new admin_settingpage('gradecategorysettings', get_string('gradecategorysettings', 'grades'));
@ -96,6 +90,15 @@ $temp->add(new admin_setting_configselect('grade_droplow', get_string('droplow',
$ADMIN->add('grades', $temp);
/// Scales and outcomes
$scales = new admin_externalpage('scales', get_string('scales'), $CFG->wwwroot.'/grade/edit/scale/index.php', 'moodle/grade:manage');
$ADMIN->add('grades', $scales);
$outcomes = new admin_externalpage('outcomes', get_string('outcomes', 'grades'), $CFG->wwwroot.'/grade/edit/outcome/index.php', 'moodle/grade:manage');
$ADMIN->add('grades', $outcomes);
$letters = new admin_externalpage('letters', get_string('letters', 'grades'), $CFG->wwwroot.'/grade/edit/letter/edit.php', 'moodle/grade:manageletters');
$ADMIN->add('grades', $letters);
// The plugins must implement a settings.php file that adds their admin settings to the $settings object
// Reports

View file

@ -187,35 +187,9 @@ function get_grade_tree(&$gtree, $element, $current_itemid=null, $errors=null) {
}
}
$icon = '<img src="'.$CFG->wwwroot.'/pix/spacer.gif" class="icon" alt=""/>' . "\n";
$icon = $gtree->get_element_icon($element);
$last = '';
$catcourseitem = false;
switch ($type) {
case 'item':
if ($object->itemtype == 'mod') {
$icon = '<img src="'.$CFG->modpixpath.'/'.$object->itemmodule.'/icon.gif" class="icon" alt="'
. get_string('modulename', $object->itemmodule).'"/>' . "\n";
} else if ($object->itemtype == 'manual') {
//TODO: add manual grading icon
if (empty($object->outcomeid)) {
$icon = '<img src="'.$CFG->pixpath.'/t/edit.gif" class="icon" alt="'
. get_string('manualgrade', 'grades').'"/>' . "\n"; // TODO: localize
} else {
$icon = '<img src="'.$CFG->pixpath.'/i/outcomes.gif" class="icon" alt="'
. get_string('outcome', 'grades').'"/>' . "\n";
}
}
break;
case 'courseitem':
case 'categoryitem':
$icon = '<img src="'.$CFG->pixpath.'/i/category_grade.gif" class="icon" alt="'.get_string('categorygrade').'"/>' . "\n"; // TODO: localize
$catcourseitem = true;
break;
case 'category':
$icon = '<img src="'.$CFG->pixpath.'/f/folder.gif" class="icon" alt="'.get_string('category').'"/>' . "\n";
break;
}
$catcourseitem = ($element['type'] == 'courseitem' or $element['type'] == 'categoryitem');
if ($type != 'category') {
$return_string .= '<li class="'.$type.'">'.$icon.$name.'</li>' . "\n";

View file

@ -42,7 +42,7 @@ class edit_category_form extends moodleform {
GRADE_AGGREGATE_EXTRACREDIT_MEAN=>get_string('aggregateextracreditmean', 'grades'));
// visible elements
$mform->addElement('header', 'general', get_string('gradecategory', 'grades'));
$mform->addElement('header', 'gradecat', get_string('gradecategory', 'grades'));
$mform->addElement('text', 'fullname', get_string('categoryname', 'grades'));
if ($CFG->grade_aggregation == -1) {
@ -62,12 +62,14 @@ class edit_category_form extends moodleform {
$mform->addElement('static', 'aggregateonlygraded', get_string('aggregateonlygraded', 'grades'));
}
if (!empty($CFG->enableoutcomes) && $CFG->grade_aggregateoutcomes == -1) {
$mform->addElement('advcheckbox', 'aggregateoutcomes', get_string('aggregateoutcomes', 'grades'));
$mform->setHelpButton('aggregateoutcomes', array(false, get_string('aggregateoutcomes', 'grades'),
false, true, false, get_string('aggregateoutcomeshelp', 'grades')));
} else {
$mform->addElement('static', 'aggregateoutcomes', get_string('aggregateoutcomes', 'grades'));
if (!empty($CFG->enableoutcomes)) {
if($CFG->grade_aggregateoutcomes == -1) {
$mform->addElement('advcheckbox', 'aggregateoutcomes', get_string('aggregateoutcomes', 'grades'));
$mform->setHelpButton('aggregateoutcomes', array(false, get_string('aggregateoutcomes', 'grades'),
false, true, false, get_string('aggregateoutcomeshelp', 'grades')));
} else {
$mform->addElement('static', 'aggregateoutcomes', get_string('aggregateoutcomes', 'grades'));
}
}
if ($CFG->grade_aggregatesubcats == -1) {
@ -111,7 +113,7 @@ class edit_category_form extends moodleform {
}
// user preferences
$mform->addElement('header', 'general', get_string('userpreferences', 'grades'));
$mform->addElement('header', 'userpref', get_string('myreportpreferences', 'grades'));
$options = array(GRADE_REPORT_PREFERENCE_DEFAULT => get_string('default', 'grades'),
GRADE_REPORT_AGGREGATION_VIEW_FULL => get_string('fullmode', 'grades'),
GRADE_REPORT_AGGREGATION_VIEW_AGGREGATES_ONLY => get_string('aggregatesonly', 'grades'),
@ -158,9 +160,11 @@ class edit_category_form extends moodleform {
$agg_el->setValue($checkbox_values[$CFG->grade_aggregateonlygraded]);
}
if ($CFG->grade_aggregateoutcomes != -1) {
$agg_el =& $mform->getElement('aggregateoutcomes');
$agg_el->setValue($checkbox_values[$CFG->grade_aggregateoutcomes]);
if (!empty($CFG->enableoutcomes)) {
if ($CFG->grade_aggregateoutcomes != -1) {
$agg_el =& $mform->getElement('aggregateoutcomes');
$agg_el->setValue($checkbox_values[$CFG->grade_aggregateoutcomes]);
}
}
if ($CFG->grade_aggregatesubcats != -1) {

View file

@ -201,35 +201,9 @@ function print_grade_tree(&$gtree, $element, $moving, &$gpr, $switch, $switchedl
$actions .= $gtree->get_hiding_icon($element, $gpr);
/// prepare icon
$icon = '<img src="'.$CFG->wwwroot.'/pix/spacer.gif" class="icon" alt=""/>';
$icon = $gtree->get_element_icon($element);
$last = '';
$catcourseitem = false;
switch ($element['type']) {
case 'item':
if ($object->itemtype == 'mod') {
$icon = '<img src="'.$CFG->modpixpath.'/'.$object->itemmodule.'/icon.gif" class="icon" alt="'
. get_string('modulename', $object->itemmodule).'"/>';
} else if ($object->itemtype == 'manual') {
//TODO: add manual grading icon
if (empty($object->outcomeid)) {
$icon = '<img src="'.$CFG->pixpath.'/t/edit.gif" class="icon" alt="'
. get_string('manualgrade', 'grades').'"/>'; // TODO: localize
} else {
$icon = '<img src="'.$CFG->pixpath.'/i/outcomes.gif" class="icon" alt="'
. get_string('outcome', 'grades').'"/>';
}
}
break;
case 'courseitem':
case 'categoryitem':
$icon = '<img src="'.$CFG->pixpath.'/i/category_grade.gif" class="icon" alt="'.get_string('categorygrade').'"/>'; // TODO: localize
$catcourseitem = true;
break;
case 'category':
$icon = '<img src="'.$CFG->pixpath.'/f/folder.gif" class="icon" alt="'.get_string('category').'"/>';
break;
}
$catcourseitem = ($element['type'] == 'courseitem' or $element['type'] == 'categoryitem');
/// prepare move target if needed
$moveto = '';

View file

@ -839,7 +839,6 @@ class grade_seq {
return 'g'.$grade_grade->id;
}
}
}
/**
@ -919,6 +918,7 @@ class grade_tree {
}
grade_tree::fill_levels($this->levels, $this->top_element, 0);
}
/**
@ -1344,6 +1344,61 @@ class grade_tree {
return $calculation_icon;
}
/**
* Returns icon of element
* @param object $element
* @param bool $spacerifnone return spacer if no icon found
* @return string icon or spacer
*/
function get_element_icon(&$element, $spacerifnone=true) {
global $CFG;
switch ($element['type']) {
case 'item':
case 'courseitem':
case 'categoryitem':
if ($element['object']->is_calculated()) {
return '<img src="'.$CFG->pixpath.'/i/calc.gif" class="icon" alt="'.get_string('calculation', 'grades').'"/>';
} else if (($element['object']->is_course_item() or $element['object']->is_category_item())
and ($element['object']->gradetype == GRADE_TYPE_SCALE or $element['object']->gradetype == GRADE_TYPE_VALUE)) {
if ($category = $element['object']->get_item_category()) {
switch ($category->aggregation) {
case GRADE_AGGREGATE_MEAN:
case GRADE_AGGREGATE_MEDIAN:
case GRADE_AGGREGATE_WEIGHTED_MEAN:
case GRADE_AGGREGATE_EXTRACREDIT_MEAN:
return '<img src="'.$CFG->pixpath.'/i/agg_mean.gif" class="icon" alt="'.get_string('aggregation', 'grades').'"/>';
//case GRADE_AGGREGATE_SUM:
//return '<img src="'.$CFG->pixpath.'/i/agg_sum.gif" class="icon" alt="'.get_string('aggregation', 'grades').'"/>';
}
}
} else if ($element['object']->itemtype == 'mod') {
return '<img src="'.$CFG->modpixpath.'/'.$element['object']->itemmodule.'/icon.gif" class="icon" alt="'
.get_string('modulename', $element['object']->itemmodule).'"/>';
} else if ($element['object']->itemtype == 'manual') {
if ($element['object']->is_outcome_item()) {
return '<img src="'.$CFG->pixpath.'/i/outcomes.gif" class="icon" alt="'.get_string('outcome', 'grades').'"/>';
} else {
//TODO: add better icon
return '<img src="'.$CFG->pixpath.'/t/edit.gif" class="icon" alt="'.get_string('manualitem', 'grades').'"/>';
}
}
break;
case 'category':
return '<img src="'.$CFG->pixpath.'/f/folder.gif" class="icon" alt="'.get_string('category', 'grades').'"/>';
}
if ($spacerifnone) {
return '<img src="'.$CFG->wwwroot.'/pix/spacer.gif" class="icon" alt=""/>';
} else {
return '';
}
}
}
?>

View file

@ -132,6 +132,8 @@ if ($perpageurl) {
}
$report->load_users();
$numusers = $report->get_numusers();
$report->load_final_grades();

View file

@ -342,9 +342,10 @@ class grade_report_grader extends grade_report {
$userids = array_keys($this->users);
if ($grades = get_records_sql($sql)) {
foreach ($grades as $graderec) {
if (in_array($graderec->userid, $userids)) {
if (in_array($graderec->userid, $userids) and array_key_exists($graderec->itemid, $this->gtree->items)) { // some items may not be present!!
$this->grades[$graderec->userid][$graderec->itemid] = new grade_grade($graderec, false);
$this->grades[$graderec->userid][$graderec->itemid]->grade_item =& $this->gtree->items[$graderec->itemid]; // db caching
}
@ -603,20 +604,23 @@ class grade_report_grader extends grade_report {
*/
function get_studentshtml() {
global $CFG, $USER;
$studentshtml = '';
$strfeedback = $this->get_lang_string("feedback");
$strgrade = $this->get_lang_string('grade');
$strfeedback = $this->get_lang_string("feedback");
$strgrade = $this->get_lang_string('grade');
$gradetabindex = 1;
$showuserimage = $this->get_pref('showuserimage');
$numusers = count($this->users);
$numusers = count($this->users);
// Preload scale objects for items with a scaleid
$scales_list = '';
$tabindices = array();
foreach ($this->gtree->items as $item) {
if (!empty($item->scaleid)) {
$scales_list .= "$item->scaleid,";
}
$tabindices[$item->id]['grade'] = $gradetabindex;
$tabindices[$item->id]['feedback'] = $gradetabindex + $numusers;
$gradetabindex += $numusers * 2;
@ -633,9 +637,13 @@ class grade_report_grader extends grade_report {
foreach ($this->users as $userid => $user) {
if ($canviewhidden) {
$hiding_affected = array();
$altered = array();
$unknown = array();
} else {
$hiding_affected = grade_grade::get_hiding_affected($this->grades[$userid], $this->gtree->items);
$altered = $hiding_affected['altered'];
$unknown = $hiding_affected['unknown'];
unset($hiding_affected);
}
$columncount = 0;
@ -651,17 +659,24 @@ class grade_report_grader extends grade_report {
foreach ($this->gtree->items as $itemid=>$unused) {
$item =& $this->gtree->items[$itemid];
$grade = $this->grades[$userid][$item->id];
// Get the decimal points preference for this item
$decimalpoints = $item->get_decimals();
$grade = $this->grades[$userid][$item->id];
$gradeval = $grade->finalgrade;
if (in_array($itemid, $unknown)) {
$gradeval = null;
} else if (array_key_exists($itemid, $altered)) {
$gradeval = $altered[$itemid];
} else {
$gradeval = $grade->finalgrade;
}
// MDL-11274
// Hide grades in the grader report if the current grader doesn't have 'moodle/grade:viewhidden'
if (!$canviewhidden and ($grade->is_hidden() or in_array($itemid, $hiding_affected))) {
if (!is_null($gradeval) and $grade->is_hidden()) {
if (!$canviewhidden and $grade->is_hidden()) {
if (!empty($CFG->grade_hiddenasdate) and !is_null($grade->finalgrade) and !$item->is_category_item() and !$item->is_course_item()) {
// the problem here is that we do not have the time when grade value was modified, 'timemodified' is general modification date for grade_grades records
$studentshtml .= '<td class="cell c'.$columncount++.'">'.userdate($grade->timecreated,get_string('strftimedatetimeshort')).'</td>';
} else {
$studentshtml .= '<td class="cell c'.$columncount++.'">-</td>';

View file

@ -137,14 +137,26 @@ class grade_report_user extends grade_report {
}
if ($canviewhidden) {
$hiding_affected = array();
$altered = array();
$unknown = array();
} else {
$hiding_affected = grade_grade::get_hiding_affected($grades, $items);
$altered = $hiding_affected['altered'];
$unknown = $hiding_affected['unknown'];
unset($hiding_affected);
}
foreach ($items as $key=>$unused) {
$grade_item =& $items[$key];
$grade_grade =& $grades[$key];
foreach ($items as $itemid=>$unused) {
$grade_item =& $items[$itemid];
$grade_grade =& $grades[$itemid];
if (in_array($itemid, $unknown)) {
$gradeval = null;
} else if (array_key_exists($itemid, $altered)) {
$gradeval = $altered[$itemid];
} else {
$gradeval = $grade_grade->finalgrade;
}
$data = array();
@ -169,47 +181,31 @@ class grade_report_user extends grade_report {
if ($grade_item->needsupdate) {
$data[] = '<span class="gradingerror">'.get_string('error').'</span>';
} else if (is_null($grade_grade->finalgrade)) {
$data[] = $excluded . '-';
} else if (!$canviewhidden and ($grade_grade->is_hidden() or in_array($grade_item->id, $hiding_affected))) {
// TODO: optinally do not show anything for hidden grades
// $data[] = '-';
if ($grade_grade->is_hidden()) {
$data[] = $excluded . '<div class="gradeddate">'.get_string('gradedon', 'grades', userdate($grade_grade->timemodified, get_string('strftimedatetimeshort'))).'</div>';
} else {
$data[] = $excluded . '-';
}
} else if (!empty($CFG->grade_hiddenasdate) and !is_null($grade_grade->finalgrade) and !$canviewhidden and $grade_grade->is_hidden()
and !$grade_item->is_category_item() and !$grade_item->is_course_item()) {
// the problem here is that we do not have the time when grade value was modified, 'timemodified' is general modification date for grade_grades records
$data[] = $excluded . '<div class="gradeddate">'.get_string('gradedon', 'grades', userdate($grade_grade->timemodified, get_string('strftimedatetimeshort'))).'</div>';
} else {
$data[] = $excluded . grade_format_gradevalue($grade_grade->finalgrade, $grade_item, true);
$data[] = $excluded . grade_format_gradevalue($gradeval, $grade_item, true);
}
/// prints percentage
if ($grade_item->needsupdate) {
$data[] = '<span class="gradingerror">'.get_string('error').'</span>';
} else if (is_null($grade_grade->finalgrade)) {
$data[] = '-';
} else if (!$canviewhidden and ($grade_grade->is_hidden() or in_array($grade_item->id, $hiding_affected))) {
$data[] = '-';
} else {
$data[] = grade_format_gradevalue($grade_grade->finalgrade, $grade_item, true, GRADE_DISPLAY_TYPE_PERCENTAGE);
$data[] = grade_format_gradevalue($gradeval, $grade_item, true, GRADE_DISPLAY_TYPE_PERCENTAGE);
}
/// prints rank
if ($grade_item->needsupdate) {
$data[] = '<span class="gradingerror">'.get_string('error').'</span>';
} else if (is_null($grade_grade->finalgrade)) {
} else if (is_null($gradeval)) {
// no grade, no rank
$data[] = '-';
} else if (!$canviewhidden and ($grade_grade->is_hidden() or in_array($grade_item->id, $hiding_affected))) {
$data[] = '-';
} else {
/// find the number of users with a higher grade
$sql = "SELECT COUNT(DISTINCT(userid))
@ -225,7 +221,7 @@ class grade_report_user extends grade_report {
if (empty($grade_grade->feedback)) {
$data[] = '&nbsp;';
} else if (!$canviewhidden and ($grade_grade->is_hidden() or in_array($grade_item->id, $hiding_affected))) {
} else if (!$canviewhidden and $grade_grade->is_hidden()) {
$data[] = '&nbsp;';
} else {

View file

@ -74,6 +74,7 @@ $string['configexportdecimalpoints'] = 'The number of decimal points to display
$string['configgradeletter'] = 'A letter or other symbol used to represent a range of grades.';
$string['configgradeletterdefault'] = 'A letter or other symbol used to represent a range of grades. Leave this field empty to use the site default (currently $a).';
$string['configgradepublishing'] = 'Enable publishing in exports and imports: Exported grades can be accessed by accessing a URL, without having to log on to a Moodle site. Grades can be imported by accessing such a URL (which means that a moodle site can import grades published by another site). By default only administrators may use this feature, please educate users before adding required capabilities to other roles (dangers of bookmark sharing and download accelerators, IP restrictions, etc.).';
$string['confighiddenasdate'] = 'If user can not see hidden grades show date instead of \'-\'.';
$string['configmeanselection'] = 'Select which types of grades will be included in the column averages. Cells with no grade can be ignored, or counted as 0 (default setting).';
$string['configquickfeedback'] = 'Quick Feedback adds a text input element in each grade cell on the grader report, allowing you to edit many grades at once. You can then click the Update button to perform all these changes at once, instead of one at a time.';
$string['configquickgrading'] = 'Quick Grading adds a text input element in each grade cell on the grader report, allowing you to edit the feedback for many grades at once. You can then click the Update button to perform all these changes at once, instead of one at a time.';
@ -163,7 +164,7 @@ $string['gradeboundary'] = 'Letter grade boundary';
$string['gradecategories'] = 'Grade categories';
$string['gradecategory'] = 'Grade Category';
$string['gradecategoryhelp'] = 'Grade Category Help';
$string['gradecategorysettings'] = 'Grade Category Settings';
$string['gradecategorysettings'] = 'Grade category settings';
$string['gradedon'] = 'Graded $a';
$string['gradedisplay'] = 'Grade display';
$string['gradedisplaytype'] = 'Grade display type';
@ -205,6 +206,7 @@ $string['gradeview'] = 'View Grade';
$string['gradeweighthelp'] = 'Grade Weight Help';
$string['groupavg'] = 'Group average';
$string['hidden'] = 'Hidden';
$string['hiddenasdate'] = 'Show date for hidden grades';
$string['hiddenuntil'] = 'Hidden until';
$string['hiddenuntildate'] = 'Hidden until: $a';
$string['hideadvanced'] = 'Hide Advanced Features';
@ -256,6 +258,7 @@ $string['locktime'] = 'Lock after';
$string['locktimedate'] = 'Locked after: $a';
$string['lowest'] = 'Lowest';
$string['lowgradeletter'] = 'Low';
$string['manualitem'] = 'Manual item';
$string['mapfrom'] = 'Map from';
$string['mapto'] = 'Map to';
$string['max'] = 'Highest';

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);
}
}
?>

BIN
pix/i/agg_mean.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

View file

Before

Width:  |  Height:  |  Size: 267 B

After

Width:  |  Height:  |  Size: 267 B

Before After
Before After