Grading grades aggregations

This commit is contained in:
David Mudrak 2010-01-04 18:17:37 +00:00
parent 2a9b468c35
commit 39411930fa
2 changed files with 242 additions and 2 deletions

View File

@ -1189,7 +1189,8 @@ class workshop {
/**
* Calculates grades for assessment for the given participant(s)
*
* Grade for submission is calculated as a weighted mean of all given grades
* Grade for assessment is calculated as a simple mean of all grading grades calculated by the grading evaluator.
* The assessment weight is not taken into account here.
*
* @param null|int|array $restrict If null, update all reviewers, otherwise update just grades for the given reviewer(s)
* @return void
@ -1197,7 +1198,50 @@ class workshop {
public function aggregate_grading_grades($restrict=null) {
global $DB;
// todo
// fetch a recordset with all assessments to process
$sql = 'SELECT a.reviewerid, a.gradinggrade, a.gradinggradeover,
ag.id AS aggregationid, ag.gradinggrade AS aggregatedgrade
FROM {workshop_assessments} a
INNER JOIN {workshop_submissions} s ON (a.submissionid = s.id)
LEFT JOIN {workshop_aggregations} ag ON (ag.userid = a.reviewerid AND ag.workshopid = s.workshopid)
WHERE s.example=0 AND s.workshopid=:workshopid'; // to be cont.
$params = array('workshopid' => $this->id);
if (is_null($restrict)) {
// update all users - no more conditions
} elseif (!empty($restrict)) {
list($usql, $uparams) = $DB->get_in_or_equal($restrict, SQL_PARAMS_NAMED);
$sql .= " AND a.reviewerid $usql";
$params = array_merge($params, $uparams);
} else {
throw new coding_exception('Empty value is not a valid parameter here');
}
$sql .= ' ORDER BY a.reviewerid'; // this is important for bulk processing
$rs = $DB->get_recordset_sql($sql, $params);
$batch = array(); // will contain a set of all assessments of a single submission
$previous = null; // a previous record in the recordset
foreach ($rs as $current) {
if (is_null($previous)) {
// we are processing the very first record in the recordset
$previous = $current;
}
if ($current->reviewerid == $previous->reviewerid) {
// we are still processing the current reviewer
$batch[] = $current;
} else {
// process all the assessments of a sigle submission
$this->aggregate_grading_grades_process($batch);
// and then start to process another reviewer
$batch = array($current);
$previous = $current;
}
}
// do not forget to process the last batch!
$this->aggregate_grading_grades_process($batch);
$rs->close();
}
/**
@ -1295,6 +1339,68 @@ class workshop {
}
}
/**
* Given an array of all assessments done by a single reviewer, calculates the final grading grade
*
* This calculates the simple mean of the passed grading grades. If, however, the grading grade
* was overridden by a teacher, the gradinggradeover value is returned and the rest of grades are ignored.
*
* @param array $assessments of stdClass(->reviewerid ->gradinggrade ->gradinggradeover ->aggregationid ->aggregatedgrade)
* @return null|float the aggregated grade rounded to numeric(10,5)
*/
protected function aggregate_grading_grades_process(array $assessments) {
global $DB;
$reviewerid = null; // the id of the reviewer being processed
$current = null; // the gradinggrade currently saved in database
$finalgrade = null; // the new grade to be calculated
$agid = null; // aggregation id
$sumgrades = 0;
$count = 0;
foreach ($assessments as $assessment) {
if (is_null($reviewerid)) {
// the id is the same in all records, fetch it during the first loop cycle
$reviewerid = $assessment->reviewerid;
}
if (is_null($agid)) {
// the id is the same in all records, fetch it during the first loop cycle
$agid = $assessment->aggregationid;
}
if (is_null($current)) {
// the currently saved grade is the same in all records, fetch it during the first loop cycle
$current = $assessment->aggregatedgrade;
}
if (!is_null($assessment->gradinggradeover)) {
// the grading grade for this assessment is overriden by a teacher
$sumgrades += $assessment->gradinggradeover;
$count++;
} else {
if (!is_null($assessment->gradinggrade)) {
$sumgrades += $assessment->gradinggrade;
$count++;
}
}
}
if ($count > 0) {
$finalgrade = grade_floatval($sumgrades / $count);
}
// check if the new final grade differs from the one stored in the database
if (grade_floats_different($finalgrade, $current)) {
// we need to save new calculation into the database
if (is_null($agid)) {
// no aggregation record yet
$record = new stdClass();
$record->workshopid = $this->id;
$record->userid = $reviewerid;
$record->gradinggrade = $finalgrade;
$DB->insert_record('workshop_aggregations', $record);
} else {
$DB->set_field('workshop_aggregations', 'gradinggrade', $finalgrade, array('id' => $agid));
}
}
}
/**
* Given a list of user ids, returns the filtered one containing just ids of users with own submission
*

View File

@ -36,6 +36,7 @@ Mock::generate(get_class($DB), 'mockDB');
class testable_workshop extends workshop {
public function __construct() {
$this->id = 16;
$this->cm = new stdClass();
$this->course = new stdClass();
$this->context = new stdClass();
@ -44,6 +45,10 @@ class testable_workshop extends workshop {
public function aggregate_submission_grades_process(array $assessments) {
parent::aggregate_submission_grades_process($assessments);
}
public function aggregate_grading_grades_process(array $assessments) {
parent::aggregate_grading_grades_process($assessments);
}
}
/**
@ -243,6 +248,135 @@ class workshop_internal_api_test extends UnitTestCase {
$this->workshop->aggregate_submission_grades_process($batch);
}
public function test_aggregate_grading_grades_process_nograding() {
global $DB;
// fixture set-up
$batch = array();
$batch[] = (object)array('reviewerid'=>2, 'gradinggrade'=>null, 'gradinggradeover'=>null, 'aggregationid'=>null, 'aggregatedgrade'=>null);
// expectation
$DB->expectNever('set_field');
// excersise SUT
$this->workshop->aggregate_grading_grades_process($batch);
}
public function test_aggregate_grading_grades_process_single_grade_new() {
global $DB;
// fixture set-up
$batch = array();
$batch[] = (object)array('reviewerid'=>3, 'gradinggrade'=>82.87670, 'gradinggradeover'=>null, 'aggregationid'=>null, 'aggregatedgrade'=>null);
// expectation
$expected = new stdClass();
$expected->workshopid = $this->workshop->id;
$expected->userid = 3;
$expected->gradinggrade = 82.87670;
$DB->expectOnce('insert_record', array('workshop_aggregations', $expected));
// excersise SUT
$this->workshop->aggregate_grading_grades_process($batch);
}
public function test_aggregate_grading_grades_process_single_grade_update() {
global $DB;
// fixture set-up
$batch = array();
$batch[] = (object)array('reviewerid'=>3, 'gradinggrade'=>90.00000, 'gradinggradeover'=>null, 'aggregationid'=>1, 'aggregatedgrade'=>82.87670);
// expectation
$DB->expectOnce('set_field', array('workshop_aggregations', 'gradinggrade', 90.00000, array('id' => 1)));
// excersise SUT
$this->workshop->aggregate_grading_grades_process($batch);
}
public function test_aggregate_grading_grades_process_single_grade_uptodate() {
global $DB;
// fixture set-up
$batch = array();
$batch[] = (object)array('reviewerid'=>3, 'gradinggrade'=>90.00000, 'gradinggradeover'=>null, 'aggregationid'=>1, 'aggregatedgrade'=>90.00000);
// expectation
$DB->expectNever('set_field');
// excersise SUT
$this->workshop->aggregate_grading_grades_process($batch);
}
public function test_aggregate_grading_grades_process_single_grade_overridden() {
global $DB;
// fixture set-up
$batch = array();
$batch[] = (object)array('reviewerid'=>4, 'gradinggrade'=>91.56700, 'gradinggradeover'=>82.32105, 'aggregationid'=>2, 'aggregatedgrade'=>91.56700);
// expectation
$DB->expectOnce('set_field', array('workshop_aggregations', 'gradinggrade', 82.32105, array('id' => 2)));
// excersise SUT
$this->workshop->aggregate_grading_grades_process($batch);
}
public function test_aggregate_grading_grades_process_multiple_grades_new() {
global $DB;
// fixture set-up
$batch = array();
$batch[] = (object)array('reviewerid'=>5, 'gradinggrade'=>99.45670, 'gradinggradeover'=>null, 'aggregationid'=>null, 'aggregatedgrade'=>null);
$batch[] = (object)array('reviewerid'=>5, 'gradinggrade'=>87.34311, 'gradinggradeover'=>null, 'aggregationid'=>null, 'aggregatedgrade'=>null);
$batch[] = (object)array('reviewerid'=>5, 'gradinggrade'=>51.12000, 'gradinggradeover'=>null, 'aggregationid'=>null, 'aggregatedgrade'=>null);
// expectation
$expected = new stdClass();
$expected->workshopid = $this->workshop->id;
$expected->userid = 5;
$expected->gradinggrade = 79.3066;
$DB->expectOnce('insert_record', array('workshop_aggregations', $expected));
// excersise SUT
$this->workshop->aggregate_grading_grades_process($batch);
}
public function test_aggregate_grading_grades_process_multiple_grades_update() {
global $DB;
// fixture set-up
$batch = array();
$batch[] = (object)array('reviewerid'=>5, 'gradinggrade'=>56.23400, 'gradinggradeover'=>null, 'aggregationid'=>2, 'aggregatedgrade'=>79.30660);
$batch[] = (object)array('reviewerid'=>5, 'gradinggrade'=>87.34311, 'gradinggradeover'=>null, 'aggregationid'=>2, 'aggregatedgrade'=>79.30660);
$batch[] = (object)array('reviewerid'=>5, 'gradinggrade'=>51.12000, 'gradinggradeover'=>null, 'aggregationid'=>2, 'aggregatedgrade'=>79.30660);
// expectation
$DB->expectOnce('set_field', array('workshop_aggregations', 'gradinggrade', 64.89904, array('id' => 2)));
// excersise SUT
$this->workshop->aggregate_grading_grades_process($batch);
}
public function test_aggregate_grading_grades_process_multiple_grades_overriden() {
global $DB;
// fixture set-up
$batch = array();
$batch[] = (object)array('reviewerid'=>5, 'gradinggrade'=>56.23400, 'gradinggradeover'=>99.45670, 'aggregationid'=>2, 'aggregatedgrade'=>64.89904);
$batch[] = (object)array('reviewerid'=>5, 'gradinggrade'=>87.34311, 'gradinggradeover'=>null, 'aggregationid'=>2, 'aggregatedgrade'=>64.89904);
$batch[] = (object)array('reviewerid'=>5, 'gradinggrade'=>51.12000, 'gradinggradeover'=>null, 'aggregationid'=>2, 'aggregatedgrade'=>64.89904);
// expectation
$DB->expectOnce('set_field', array('workshop_aggregations', 'gradinggrade', 79.30660, array('id' => 2)));
// excersise SUT
$this->workshop->aggregate_grading_grades_process($batch);
}
public function test_aggregate_grading_grades_process_multiple_grades_one_missing() {
global $DB;
// fixture set-up
$batch = array();
$batch[] = (object)array('reviewerid'=>6, 'gradinggrade'=>50.00000, 'gradinggradeover'=>null, 'aggregationid'=>3, 'aggregatedgrade'=>100.00000);
$batch[] = (object)array('reviewerid'=>6, 'gradinggrade'=>null, 'gradinggradeover'=>null, 'aggregationid'=>3, 'aggregatedgrade'=>100.00000);
$batch[] = (object)array('reviewerid'=>6, 'gradinggrade'=>52.20000, 'gradinggradeover'=>null, 'aggregationid'=>3, 'aggregatedgrade'=>100.00000);
// expectation
$DB->expectOnce('set_field', array('workshop_aggregations', 'gradinggrade', 51.10000, array('id' => 3)));
// excersise SUT
$this->workshop->aggregate_grading_grades_process($batch);
}
public function test_aggregate_grading_grades_process_multiple_grades_missing_overridden() {
global $DB;
// fixture set-up
$batch = array();
$batch[] = (object)array('reviewerid'=>6, 'gradinggrade'=>50.00000, 'gradinggradeover'=>null, 'aggregationid'=>3, 'aggregatedgrade'=>100.00000);
$batch[] = (object)array('reviewerid'=>6, 'gradinggrade'=>null, 'gradinggradeover'=>69.00000, 'aggregationid'=>3, 'aggregatedgrade'=>100.00000);
$batch[] = (object)array('reviewerid'=>6, 'gradinggrade'=>52.20000, 'gradinggradeover'=>null, 'aggregationid'=>3, 'aggregatedgrade'=>100.00000);
// expectation
$DB->expectOnce('set_field', array('workshop_aggregations', 'gradinggrade', 57.06667, array('id' => 3)));
// excersise SUT
$this->workshop->aggregate_grading_grades_process($batch);
}
public function test_percent_to_value() {
// fixture setup
$total = 185;