Exemplo n.º 1
0
 /**
  * Calculates the aggregated grade given by the reviewer
  *
  * @param array $grades Grade records as returned by {@link get_current_assessment_data}
  * @uses $this->dimensions
  * @return float|null   Raw grade (from 0.00000 to 100.00000) for submission as suggested by the peer
  */
 protected function calculate_peer_grade(array $grades)
 {
     if (empty($grades)) {
         return null;
     }
     $sumgrades = 0;
     $sumweights = 0;
     foreach ($grades as $grade) {
         $dimension = $this->dimensions[$grade->dimensionid];
         if ($dimension->weight < 0) {
             throw new coding_exception('Negative weights are not supported any more. Something is wrong with your data');
         }
         if (grade_floats_equal($dimension->weight, 0) or grade_floats_equal($dimension->grade, 0)) {
             // does not influence the final grade
             continue;
         }
         if ($dimension->grade < 0) {
             // this is a scale
             $scaleid = -$dimension->grade;
             $sumgrades += $this->scale_to_grade($scaleid, $grade->grade) * $dimension->weight * 100;
             $sumweights += $dimension->weight;
         } else {
             // regular grade
             $sumgrades += $grade->grade / $dimension->grade * $dimension->weight * 100;
             $sumweights += $dimension->weight;
         }
     }
     if ($sumweights === 0) {
         return 0;
     }
     return grade_floatval($sumgrades / $sumweights);
 }
Exemplo n.º 2
0
 /**
  * Factory method returning an instance of an assessment form
  *
  * @param moodle_url $actionurl URL of form handler, defaults to auto detect the current url
  * @param string $mode          Mode to open the form in: preview/assessment/readonly
  * @param stdClass $assessment  The current assessment
  * @param bool $editable
  * @param array $options
  */
 public function get_assessment_form(moodle_url $actionurl = null, $mode = 'preview', stdclass $assessment = null, $editable = true, $options = array())
 {
     global $CFG;
     // needed because the included files use it
     global $DB;
     require_once dirname(__FILE__) . '/assessment_form.php';
     $fields = $this->prepare_form_fields($this->dimensions);
     $nodimensions = count($this->dimensions);
     // rewrite URLs to the embeded files
     for ($i = 0; $i < $nodimensions; $i++) {
         $fields->{'description__idx_' . $i} = file_rewrite_pluginfile_urls($fields->{'description__idx_' . $i}, 'pluginfile.php', $this->workshop->context->id, 'workshopform_rubric', 'description', $fields->{'dimensionid__idx_' . $i});
     }
     if ('assessment' === $mode and !empty($assessment)) {
         // load the previously saved assessment data
         $grades = $this->get_current_assessment_data($assessment);
         $current = new stdclass();
         for ($i = 0; $i < $nodimensions; $i++) {
             $dimid = $fields->{'dimensionid__idx_' . $i};
             if (isset($grades[$dimid])) {
                 $givengrade = $grades[$dimid]->grade;
                 // find a level with this grade
                 $levelid = null;
                 foreach ($this->dimensions[$dimid]->levels as $level) {
                     if (grade_floats_equal($level->grade, $givengrade)) {
                         $levelid = $level->id;
                         break;
                     }
                 }
                 $current->{'gradeid__idx_' . $i} = $grades[$dimid]->id;
                 $current->{'chosenlevelid__idx_' . $i} = $levelid;
             }
         }
     }
     // set up the required custom data common for all strategies
     $customdata['strategy'] = $this;
     $customdata['workshop'] = $this->workshop;
     $customdata['mode'] = $mode;
     $customdata['options'] = $options;
     // set up strategy-specific custom data
     $customdata['nodims'] = $nodimensions;
     $customdata['fields'] = $fields;
     $customdata['current'] = isset($current) ? $current : null;
     $attributes = array('class' => 'assessmentform rubric ' . $this->config->layout);
     $formclassname = 'workshop_rubric_' . $this->config->layout . '_assessment_form';
     return new $formclassname($actionurl, $customdata, 'post', '', $attributes, $editable);
 }
Exemplo n.º 3
0
 /**
  * Set the flags on the grade_grade items to indicate how individual grades are used
  * in the aggregation.
  *
  * WARNING: This function is called a lot during gradebook recalculation, be very performance considerate.
  *
  * @param int $userid The user we have aggregated the grades for.
  * @param array $usedweights An array with keys for each of the grade_item columns included in the aggregation. The value are the relative weight.
  * @param array $novalue An array with keys for each of the grade_item columns skipped because
  *                       they had no value in the aggregation.
  * @param array $dropped An array with keys for each of the grade_item columns dropped
  *                       because of any drop lowest/highest settings in the aggregation.
  * @param array $extracredit An array with keys for each of the grade_item columns
  *                       considered extra credit by the aggregation.
  */
 private function set_usedinaggregation($userid, $usedweights, $novalue, $dropped, $extracredit)
 {
     global $DB;
     // We want to know all current user grades so we can decide whether they need to be updated or they already contain the
     // expected value.
     $sql = "SELECT gi.id, gg.aggregationstatus, gg.aggregationweight FROM {grade_grades} gg\n                  JOIN {grade_items} gi ON (gg.itemid = gi.id)\n                 WHERE gg.userid = :userid";
     $params = array('categoryid' => $this->id, 'userid' => $userid);
     // These are all grade_item ids which grade_grades will NOT end up being 'unknown' (because they are not unknown or
     // because we will update them to something different that 'unknown').
     $giids = array_keys($usedweights + $novalue + $dropped + $extracredit);
     if ($giids) {
         // We include grade items that might not be in categoryid.
         list($itemsql, $itemlist) = $DB->get_in_or_equal($giids, SQL_PARAMS_NAMED, 'gg');
         $sql .= ' AND (gi.categoryid = :categoryid OR gi.id ' . $itemsql . ')';
         $params = $params + $itemlist;
     } else {
         $sql .= ' AND gi.categoryid = :categoryid';
     }
     $currentgrades = $DB->get_recordset_sql($sql, $params);
     // We will store here the grade_item ids that need to be updated on db.
     $toupdate = array();
     if ($currentgrades->valid()) {
         // Iterate through the user grades to see if we really need to update any of them.
         foreach ($currentgrades as $currentgrade) {
             // Unset $usedweights that we do not need to update.
             if (!empty($usedweights) && isset($usedweights[$currentgrade->id]) && $currentgrade->aggregationstatus === 'used') {
                 // We discard the ones that already have the contribution specified in $usedweights and are marked as 'used'.
                 if (grade_floats_equal($currentgrade->aggregationweight, $usedweights[$currentgrade->id])) {
                     unset($usedweights[$currentgrade->id]);
                 }
                 // Used weights can be present in multiple set_usedinaggregation arguments.
                 if (!isset($novalue[$currentgrade->id]) && !isset($dropped[$currentgrade->id]) && !isset($extracredit[$currentgrade->id])) {
                     continue;
                 }
             }
             // No value grades.
             if (!empty($novalue) && isset($novalue[$currentgrade->id])) {
                 if ($currentgrade->aggregationstatus !== 'novalue' || grade_floats_different($currentgrade->aggregationweight, 0)) {
                     $toupdate['novalue'][] = $currentgrade->id;
                 }
                 continue;
             }
             // Dropped grades.
             if (!empty($dropped) && isset($dropped[$currentgrade->id])) {
                 if ($currentgrade->aggregationstatus !== 'dropped' || grade_floats_different($currentgrade->aggregationweight, 0)) {
                     $toupdate['dropped'][] = $currentgrade->id;
                 }
                 continue;
             }
             // Extra credit grades.
             if (!empty($extracredit) && isset($extracredit[$currentgrade->id])) {
                 // If this grade item is already marked as 'extra' and it already has the provided $usedweights value would be
                 // silly to update to 'used' to later update to 'extra'.
                 if (!empty($usedweights) && isset($usedweights[$currentgrade->id]) && grade_floats_equal($currentgrade->aggregationweight, $usedweights[$currentgrade->id])) {
                     unset($usedweights[$currentgrade->id]);
                 }
                 // Update the item to extra if it is not already marked as extra in the database or if the item's
                 // aggregationweight will be updated when going through $usedweights items.
                 if ($currentgrade->aggregationstatus !== 'extra' || !empty($usedweights) && isset($usedweights[$currentgrade->id])) {
                     $toupdate['extracredit'][] = $currentgrade->id;
                 }
                 continue;
             }
             // If is not in any of the above groups it should be set to 'unknown', checking that the item is not already
             // unknown, if it is we don't need to update it.
             if ($currentgrade->aggregationstatus !== 'unknown' || grade_floats_different($currentgrade->aggregationweight, 0)) {
                 $toupdate['unknown'][] = $currentgrade->id;
             }
         }
         $currentgrades->close();
     }
     // Update items to 'unknown' status.
     if (!empty($toupdate['unknown'])) {
         list($itemsql, $itemlist) = $DB->get_in_or_equal($toupdate['unknown'], SQL_PARAMS_NAMED, 'g');
         $itemlist['userid'] = $userid;
         $sql = "UPDATE {grade_grades}\n                       SET aggregationstatus = 'unknown',\n                           aggregationweight = 0\n                     WHERE itemid {$itemsql} AND userid = :userid";
         $DB->execute($sql, $itemlist);
     }
     // Update items to 'used' status and setting the proper weight.
     if (!empty($usedweights)) {
         // The usedweights items are updated individually to record the weights.
         foreach ($usedweights as $gradeitemid => $contribution) {
             $sql = "UPDATE {grade_grades}\n                           SET aggregationstatus = 'used',\n                               aggregationweight = :contribution\n                         WHERE itemid = :itemid AND userid = :userid";
             $params = array('contribution' => $contribution, 'itemid' => $gradeitemid, 'userid' => $userid);
             $DB->execute($sql, $params);
         }
     }
     // Update items to 'novalue' status.
     if (!empty($toupdate['novalue'])) {
         list($itemsql, $itemlist) = $DB->get_in_or_equal($toupdate['novalue'], SQL_PARAMS_NAMED, 'g');
         $itemlist['userid'] = $userid;
         $sql = "UPDATE {grade_grades}\n                       SET aggregationstatus = 'novalue',\n                           aggregationweight = 0\n                     WHERE itemid {$itemsql} AND userid = :userid";
         $DB->execute($sql, $itemlist);
     }
     // Update items to 'dropped' status.
     if (!empty($toupdate['dropped'])) {
         list($itemsql, $itemlist) = $DB->get_in_or_equal($toupdate['dropped'], SQL_PARAMS_NAMED, 'g');
         $itemlist['userid'] = $userid;
         $sql = "UPDATE {grade_grades}\n                       SET aggregationstatus = 'dropped',\n                           aggregationweight = 0\n                     WHERE itemid {$itemsql} AND userid = :userid";
         $DB->execute($sql, $itemlist);
     }
     // Update items to 'extracredit' status.
     if (!empty($toupdate['extracredit'])) {
         list($itemsql, $itemlist) = $DB->get_in_or_equal($toupdate['extracredit'], SQL_PARAMS_NAMED, 'g');
         $itemlist['userid'] = $userid;
         $DB->set_field_select('grade_grades', 'aggregationstatus', 'extra', "itemid {$itemsql} AND userid = :userid", $itemlist);
     }
 }