/** * Update the aggregation fields when the aggregation changed. * * This method should always be called when the aggregation has changed, but also when * the item was moved to another category, even it if uses the same aggregation method. * * Some values such as the weight only make sense within a category, once moved the * values should be reset to let the user adapt them accordingly. * * Note that this method does not save the grade item. * {@link grade_item::update()} has to be called manually after using this method. * * @param int $from Aggregation method constant value. * @param int $to Aggregation method constant value. * @return boolean True when at least one field was changed, false otherwise */ public function set_aggregation_fields_for_aggregation($from, $to) { $defaults = grade_category::get_default_aggregation_coefficient_values($to); $origaggregationcoef = $this->aggregationcoef; $origaggregationcoef2 = $this->aggregationcoef2; $origweighoverride = $this->weightoverride; if ($from == GRADE_AGGREGATE_SUM && $to == GRADE_AGGREGATE_SUM && $this->weightoverride) { // Do nothing. We are switching from SUM to SUM and the weight is overriden, // a teacher would not expect any change in this situation. } else { if ($from == GRADE_AGGREGATE_WEIGHTED_MEAN && $to == GRADE_AGGREGATE_WEIGHTED_MEAN) { // Do nothing. The weights can be kept in this case. } else { if (in_array($from, array(GRADE_AGGREGATE_SUM, GRADE_AGGREGATE_EXTRACREDIT_MEAN, GRADE_AGGREGATE_WEIGHTED_MEAN2)) && in_array($to, array(GRADE_AGGREGATE_SUM, GRADE_AGGREGATE_EXTRACREDIT_MEAN, GRADE_AGGREGATE_WEIGHTED_MEAN2))) { // Reset all but the the extra credit field. $this->aggregationcoef2 = $defaults['aggregationcoef2']; $this->weightoverride = $defaults['weightoverride']; if ($to != GRADE_AGGREGATE_EXTRACREDIT_MEAN) { // Normalise extra credit, except for 'Mean with extra credit' which supports higher values than 1. $this->aggregationcoef = min(1, $this->aggregationcoef); } } else { // Reset all. $this->aggregationcoef = $defaults['aggregationcoef']; $this->aggregationcoef2 = $defaults['aggregationcoef2']; $this->weightoverride = $defaults['weightoverride']; } } } $acoefdiff = grade_floats_different($origaggregationcoef, $this->aggregationcoef); $acoefdiff2 = grade_floats_different($origaggregationcoef2, $this->aggregationcoef2); $weightoverride = grade_floats_different($origweighoverride, $this->weightoverride); return $acoefdiff || $acoefdiff2 || $weightoverride; }
} if ($parent_category->aggregation == GRADE_AGGREGATE_SUM) { $item->aggregationcoef2 = format_float($item->aggregationcoef2 * 100.0); } $item->cancontrolvisibility = $grade_item->can_control_visibility(); $mform = new edit_item_form(null, array('current' => $item, 'gpr' => $gpr)); if ($mform->is_cancelled()) { redirect($returnurl); } else { if ($data = $mform->get_data(false)) { // This is a new item, and the category chosen is different than the default category. if (empty($grade_item->id) && isset($data->parentcategory) && $parent_category->id != $data->parentcategory) { $parent_category = grade_category::fetch(array('id' => $data->parentcategory)); } // If unset, give the aggregation values a default based on parent aggregation method. $defaults = grade_category::get_default_aggregation_coefficient_values($parent_category->aggregation); if (!isset($data->aggregationcoef) || $data->aggregationcoef == '') { $data->aggregationcoef = $defaults['aggregationcoef']; } if (!isset($data->weightoverride)) { $data->weightoverride = $defaults['weightoverride']; } if (!isset($data->gradepass) || $data->gradepass == '') { $data->gradepass = 0; } if (!isset($data->grademin) || $data->grademin == '') { $data->grademin = 0; } $hidden = empty($data->hidden) ? 0 : $data->hidden; $hiddenuntil = empty($data->hiddenuntil) ? 0 : $data->hiddenuntil; unset($data->hidden);
public function test_set_aggregation_fields_for_aggregation() { $course = $this->getDataGenerator()->create_course(); $gi = new grade_item(array('courseid' => $course->id, 'itemtype' => 'manual'), false); $methods = array(GRADE_AGGREGATE_MEAN, GRADE_AGGREGATE_MEDIAN, GRADE_AGGREGATE_MIN, GRADE_AGGREGATE_MAX, GRADE_AGGREGATE_MODE, GRADE_AGGREGATE_WEIGHTED_MEAN, GRADE_AGGREGATE_WEIGHTED_MEAN2, GRADE_AGGREGATE_EXTRACREDIT_MEAN, GRADE_AGGREGATE_SUM); // Switching from and to the same aggregation using the defaults. foreach ($methods as $method) { $defaults = grade_category::get_default_aggregation_coefficient_values($method); $gi->aggregationcoef = $defaults['aggregationcoef']; $gi->aggregationcoef2 = $defaults['aggregationcoef2']; $gi->weightoverride = $defaults['weightoverride']; $this->assertFalse($gi->set_aggregation_fields_for_aggregation($method, $method)); $this->assertEquals($defaults['aggregationcoef'], $gi->aggregationcoef); $this->assertEquals($defaults['aggregationcoef2'], $gi->aggregationcoef2); $this->assertEquals($defaults['weightoverride'], $gi->weightoverride); } // Extra credit is kept across aggregation methods that support it. foreach ($methods as $from) { $fromsupportsec = grade_category::aggregation_uses_extracredit($from); $fromdefaults = grade_category::get_default_aggregation_coefficient_values($from); foreach ($methods as $to) { $tosupportsec = grade_category::aggregation_uses_extracredit($to); $todefaults = grade_category::get_default_aggregation_coefficient_values($to); // Set the item to be extra credit, if supported. if ($fromsupportsec) { $gi->aggregationcoef = 1; } else { $gi->aggregationcoef = $fromdefaults['aggregationcoef']; } // We ignore those fields, we know it is never used for extra credit. $gi->aggregationcoef2 = $todefaults['aggregationcoef2']; $gi->weightoverride = $todefaults['weightoverride']; if ($fromsupportsec && $tosupportsec) { $this->assertFalse($gi->set_aggregation_fields_for_aggregation($from, $to), "From: {$from}, to: {$to}"); $this->assertEquals(1, $gi->aggregationcoef); } else { if ($fromsupportsec && !$tosupportsec) { if ($to == GRADE_AGGREGATE_WEIGHTED_MEAN) { // Special case, aggregationcoef is used but for weights. $this->assertFalse($gi->set_aggregation_fields_for_aggregation($from, $to), "From: {$from}, to: {$to}"); $this->assertEquals($todefaults['aggregationcoef'], $gi->aggregationcoef); } else { $this->assertTrue($gi->set_aggregation_fields_for_aggregation($from, $to), "From: {$from}, to: {$to}"); $this->assertEquals($todefaults['aggregationcoef'], $gi->aggregationcoef); } } else { // The source does not support extra credit, everything will be reset. if (($from == GRADE_AGGREGATE_WEIGHTED_MEAN || $to == GRADE_AGGREGATE_WEIGHTED_MEAN) && $from != $to) { // Special case, aggregationcoef is used but for weights. $this->assertTrue($gi->set_aggregation_fields_for_aggregation($from, $to), "From: {$from}, to: {$to}"); $this->assertEquals($todefaults['aggregationcoef'], $gi->aggregationcoef); } else { $this->assertFalse($gi->set_aggregation_fields_for_aggregation($from, $to), "From: {$from}, to: {$to}"); $this->assertEquals($todefaults['aggregationcoef'], $gi->aggregationcoef); } } } } } // Extra credit can be higher than one for GRADE_AGGREGATE_EXTRACREDIT_MEAN, but will be normalised for others. $from = GRADE_AGGREGATE_EXTRACREDIT_MEAN; $fromdefaults = grade_category::get_default_aggregation_coefficient_values($from); foreach ($methods as $to) { if (!grade_category::aggregation_uses_extracredit($to)) { continue; } $todefaults = grade_category::get_default_aggregation_coefficient_values($to); $gi->aggregationcoef = 8; // Ignore those fields, they are not used for extra credit. $gi->aggregationcoef2 = $todefaults['aggregationcoef2']; $gi->weightoverride = $todefaults['weightoverride']; if ($to == $from) { $this->assertFalse($gi->set_aggregation_fields_for_aggregation($from, $to), "From: {$from}, to: {$to}"); $this->assertEquals(8, $gi->aggregationcoef); } else { $this->assertTrue($gi->set_aggregation_fields_for_aggregation($from, $to), "From: {$from}, to: {$to}"); $this->assertEquals(1, $gi->aggregationcoef); } } // Weights are reset. $from = GRADE_AGGREGATE_SUM; $fromdefaults = grade_category::get_default_aggregation_coefficient_values($from); $gi->aggregationcoef = $fromdefaults['aggregationcoef']; $gi->aggregationcoef2 = 0.321; $gi->weightoverride = $fromdefaults['weightoverride']; $to = GRADE_AGGREGATE_WEIGHTED_MEAN; $todefaults = grade_category::get_default_aggregation_coefficient_values($to); $this->assertTrue($gi->set_aggregation_fields_for_aggregation($from, $to), "From: {$from}, to: {$to}"); $this->assertEquals($todefaults['aggregationcoef'], $gi->aggregationcoef); $this->assertEquals($todefaults['aggregationcoef2'], $gi->aggregationcoef2); $this->assertEquals($todefaults['weightoverride'], $gi->weightoverride); $gi->aggregationcoef = $fromdefaults['aggregationcoef']; $gi->aggregationcoef2 = 0.321; $gi->weightoverride = $fromdefaults['weightoverride']; $to = GRADE_AGGREGATE_SUM; $todefaults = grade_category::get_default_aggregation_coefficient_values($to); $this->assertTrue($gi->set_aggregation_fields_for_aggregation($from, $to), "From: {$from}, to: {$to}"); $this->assertEquals($todefaults['aggregationcoef'], $gi->aggregationcoef); $this->assertEquals($todefaults['aggregationcoef2'], $gi->aggregationcoef2); $this->assertEquals($todefaults['weightoverride'], $gi->weightoverride); // Weight is kept when using SUM with weight override. $from = GRADE_AGGREGATE_SUM; $fromdefaults = grade_category::get_default_aggregation_coefficient_values($from); $gi->aggregationcoef = $fromdefaults['aggregationcoef']; $gi->aggregationcoef2 = 0.321; $gi->weightoverride = 1; $to = GRADE_AGGREGATE_SUM; $todefaults = grade_category::get_default_aggregation_coefficient_values($to); $this->assertFalse($gi->set_aggregation_fields_for_aggregation($from, $to), "From: {$from}, to: {$to}"); $this->assertEquals($todefaults['aggregationcoef'], $gi->aggregationcoef); $this->assertEquals(0.321, $gi->aggregationcoef2); $this->assertEquals(1, $gi->weightoverride); $gi->aggregationcoef2 = 0.321; $gi->aggregationcoef = $fromdefaults['aggregationcoef']; $gi->weightoverride = 1; $to = GRADE_AGGREGATE_WEIGHTED_MEAN; $todefaults = grade_category::get_default_aggregation_coefficient_values($to); $this->assertTrue($gi->set_aggregation_fields_for_aggregation($from, $to), "From: {$from}, to: {$to}"); $this->assertEquals($todefaults['aggregationcoef'], $gi->aggregationcoef); $this->assertEquals($todefaults['aggregationcoef2'], $gi->aggregationcoef2); $this->assertEquals($todefaults['weightoverride'], $gi->weightoverride); // Weight is kept when staying in weighted mean. $from = GRADE_AGGREGATE_WEIGHTED_MEAN; $fromdefaults = grade_category::get_default_aggregation_coefficient_values($from); $gi->aggregationcoef = 18; $gi->aggregationcoef2 = $fromdefaults['aggregationcoef2']; $gi->weightoverride = $fromdefaults['weightoverride']; $to = GRADE_AGGREGATE_WEIGHTED_MEAN; $todefaults = grade_category::get_default_aggregation_coefficient_values($to); $this->assertFalse($gi->set_aggregation_fields_for_aggregation($from, $to), "From: {$from}, to: {$to}"); $this->assertEquals(18, $gi->aggregationcoef); $this->assertEquals($todefaults['aggregationcoef2'], $gi->aggregationcoef2); $this->assertEquals($todefaults['weightoverride'], $gi->weightoverride); $gi->aggregationcoef = 18; $gi->aggregationcoef2 = $fromdefaults['aggregationcoef2']; $gi->weightoverride = $fromdefaults['weightoverride']; $to = GRADE_AGGREGATE_SUM; $todefaults = grade_category::get_default_aggregation_coefficient_values($to); $this->assertTrue($gi->set_aggregation_fields_for_aggregation($from, $to), "From: {$from}, to: {$to}"); $this->assertEquals($todefaults['aggregationcoef'], $gi->aggregationcoef); $this->assertEquals($todefaults['aggregationcoef2'], $gi->aggregationcoef2); $this->assertEquals($todefaults['weightoverride'], $gi->weightoverride); }