예제 #1
0
파일: lib.php 프로젝트: nigeli/moodle
    /**
     * Converts <ELEMENT> into <workshopform_numerrors_dimension> and stores it for later writing
     *
     * @return array to be written to workshop.xml
     */
    public function process_legacy_element($data, $raw) {

        $workshop = $this->parenthandler->get_current_workshop();

        $mapping = array();
        $mapping['id'] = $data['id'];
        $mapping['nonegative'] = $data['elementno'];
        if ($workshop['grade'] == 0 or $data['maxscore'] == 0) {
            $mapping['grade'] = 0;
        } else {
            $mapping['grade'] = grade_floatval($data['maxscore'] / $workshop['grade'] * 100);
        }
        $this->mappings[] = $mapping;

        $converted = null;

        if (trim($data['description']) and $data['description'] <> '@@ GRADE_MAPPING_ELEMENT @@') {
            // prepare a fake record and re-use the upgrade logic
            $fakerecord = (object)$data;
            $converted = (array)workshopform_numerrors_upgrade_element($fakerecord, 12345678);
            unset($converted['workshopid']);

            $converted['id'] = $data['id'];
            $this->dimensions[] = $converted;
        }

        return $converted;
    }
예제 #2
0
파일: lib.php 프로젝트: nuckey/moodle
 /**
  * Returns a grade 0.00000 to 100.00000 for the given number of errors
  *
  * This is where we use the mapping table defined by the teacher. If a grade for the given
  * number of errors (negative assertions) is not defined, the most recently defined one is used.
  * Example of the defined mapping:
  * Number of errors | Grade
  *                0 | 100%  (always)
  *                1 | -     (not defined)
  *                2 | 80%
  *                3 | 60%
  *                4 | -
  *                5 | 30%
  *                6 | 0%
  * With this mapping, one error is mapped to 100% grade and 4 errors is mapped to 60%.
  *
  * @param mixed $numerrors Number of errors
  * @return float          Raw grade (0.00000 to 100.00000) for the given number of negative assertions
  */
 protected function errors_to_grade($numerrors) {
     $grade = 100.00000;
     for ($i = 1; $i <= $numerrors; $i++) {
         if (isset($this->mappings[$i])) {
             $grade = $this->mappings[$i]->grade;
         }
     }
     if ($grade > 100.00000) {
         $grade = 100.00000;
     }
     if ($grade < 0.00000) {
         $grade = 0.00000;
     }
     return grade_floatval($grade);
 }
예제 #3
0
파일: lib.php 프로젝트: vuchannguyen/web
 /**
  * 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;
     }
     // summarize the grades given in rubrics
     $sumgrades = 0;
     foreach ($grades as $grade) {
         $sumgrades += $grade->grade;
     }
     // get the minimal and maximal possible grade (sum of minimal/maximal grades across all dimensions)
     $mingrade = 0;
     $maxgrade = 0;
     foreach ($this->dimensions as $dimension) {
         $mindimensiongrade = null;
         $maxdimensiongrade = null;
         foreach ($dimension->levels as $level) {
             if (is_null($mindimensiongrade) or $level->grade < $mindimensiongrade) {
                 $mindimensiongrade = $level->grade;
             }
             if (is_null($maxdimensiongrade) or $level->grade > $maxdimensiongrade) {
                 $maxdimensiongrade = $level->grade;
             }
         }
         $mingrade += $mindimensiongrade;
         $maxgrade += $maxdimensiongrade;
     }
     if ($maxgrade - $mingrade > 0) {
         return grade_floatval(100 * ($sumgrades - $mingrade) / ($maxgrade - $mingrade));
     } else {
         return null;
     }
 }
예제 #4
0
 /**
  * Apply a grade from a grading form to a user (may be called multiple times for a group submission).
  *
  * @param stdClass $formdata - the data from the form
  * @param int $userid - the user to apply the grade to
  * @param int $attemptnumber - The attempt number to apply the grade to.
  * @return void
  */
 protected function apply_grade_to_user($formdata, $userid, $attemptnumber)
 {
     global $USER, $CFG, $DB;
     $grade = $this->get_user_grade($userid, true, $attemptnumber);
     $gradingdisabled = $this->grading_disabled($userid);
     $gradinginstance = $this->get_grading_instance($userid, $grade, $gradingdisabled);
     if (!$gradingdisabled) {
         if ($gradinginstance) {
             $grade->grade = $gradinginstance->submit_and_get_grade($formdata->advancedgrading, $grade->id);
         } else {
             // Handle the case when grade is set to No Grade.
             if (isset($formdata->grade)) {
                 $grade->grade = grade_floatval(unformat_float($formdata->grade));
             }
         }
         if (isset($formdata->workflowstate) || isset($formdata->allocatedmarker)) {
             $flags = $this->get_user_flags($userid, true);
             $flags->workflowstate = isset($formdata->workflowstate) ? $formdata->workflowstate : $flags->workflowstate;
             $flags->allocatedmarker = isset($formdata->allocatedmarker) ? $formdata->allocatedmarker : $flags->allocatedmarker;
             $this->update_user_flags($flags);
         }
     }
     $grade->grader = $USER->id;
     $adminconfig = $this->get_admin_config();
     $gradebookplugin = $adminconfig->feedback_plugin_for_gradebook;
     // Call save in plugins.
     foreach ($this->feedbackplugins as $plugin) {
         if ($plugin->is_enabled() && $plugin->is_visible()) {
             if (!$plugin->save($grade, $formdata)) {
                 $result = false;
                 print_error($plugin->get_error());
             }
             if ('assignfeedback_' . $plugin->get_type() == $gradebookplugin) {
                 // This is the feedback plugin chose to push comments to the gradebook.
                 $grade->feedbacktext = $plugin->text_for_gradebook($grade);
                 $grade->feedbackformat = $plugin->format_for_gradebook($grade);
             }
         }
     }
     $this->update_grade($grade);
     $this->notify_grade_modified($grade);
     $addtolog = $this->add_to_log('grade submission', $this->format_grade_for_log($grade), '', true);
     $params = array('context' => $this->context, 'objectid' => $grade->id, 'relateduserid' => $userid);
     $event = \mod_assign\event\submission_graded::create($params);
     $event->set_legacy_logdata($addtolog);
     $event->trigger();
 }
예제 #5
0
   /**
     * Apply a grade from a grading form to a user (may be called multiple times for a group submission)
     *
     * @param stdClass $formdata - the data from the form
     * @param int $userid - the user to apply the grade to
     * @return void
     */
    private function apply_grade_to_user($formdata, $userid) {
        global $USER, $CFG, $DB;

        $grade = $this->get_user_grade($userid, true);
        $gradingdisabled = $this->grading_disabled($userid);
        $gradinginstance = $this->get_grading_instance($userid, $gradingdisabled);
        if (!$gradingdisabled) {
            if ($gradinginstance) {
                $grade->grade = $gradinginstance->submit_and_get_grade($formdata->advancedgrading, $grade->id);
            } else {
                // Handle the case when grade is set to No Grade.
                if (isset($formdata->grade)) {
                    $grade->grade= grade_floatval(unformat_float($formdata->grade));
                }
            }
        }
        $grade->grader= $USER->id;

        $adminconfig = $this->get_admin_config();
        $gradebookplugin = $adminconfig->feedback_plugin_for_gradebook;

        // Call save in plugins.
        foreach ($this->feedbackplugins as $plugin) {
            if ($plugin->is_enabled() && $plugin->is_visible()) {
                if (!$plugin->save($grade, $formdata)) {
                    $result = false;
                    print_error($plugin->get_error());
                }
                if (('assignfeedback_' . $plugin->get_type()) == $gradebookplugin) {
                    // This is the feedback plugin chose to push comments to the gradebook.
                    $grade->feedbacktext = $plugin->text_for_gradebook($grade);
                    $grade->feedbackformat = $plugin->format_for_gradebook($grade);
                }
            }
        }
        $this->update_grade($grade);
        $user = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST);

        $this->add_to_log('grade submission', $this->format_grade_for_log($grade));
    }
예제 #6
0
파일: lib.php 프로젝트: alanaipe2015/moodle
 /**
  * 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);
 }
예제 #7
0
/**
 * Compare two float numbers safely. Uses 5 decimals php precision. Nulls accepted too.
 * Used for skipping of db updates
 * @param float $f1
 * @param float $f2
 * @return true if different
 */
function grade_floats_different($f1, $f2)
{
    // note: db rounding for 10,5 is different from php round() function
    return grade_floatval($f1) !== grade_floatval($f2);
}
예제 #8
0
파일: grade_item.php 프로젝트: r007/PMoodle
 /**
  * In addition to update() as defined in grade_object, handle the grade_outcome and grade_scale objects.
  * Force regrading if necessary, rounds the float numbers using php function,
  * the reason is we need to compare the db value with computed number to skip regrading if possible.
  * @param string $source from where was the object inserted (mod/forum, manual, etc.)
  * @return boolean success
  */
 function update($source = null)
 {
     // reset caches
     $this->dependson_cache = null;
     // Retrieve scale and infer grademax/min from it if needed
     $this->load_scale();
     // make sure there is not 0 in outcomeid
     if (empty($this->outcomeid)) {
         $this->outcomeid = null;
     }
     if ($this->qualifies_for_regrading()) {
         $this->force_regrading();
     }
     $this->timemodified = time();
     $this->grademin = grade_floatval($this->grademin);
     $this->grademax = grade_floatval($this->grademax);
     $this->multfactor = grade_floatval($this->multfactor);
     $this->plusfactor = grade_floatval($this->plusfactor);
     $this->aggregationcoef = grade_floatval($this->aggregationcoef);
     return parent::update($source);
 }
예제 #9
0
 /**
  * Recalculate the weights of the grade items in this category.
  *
  * The category total is not updated here, a further call to
  * {@link self::auto_update_max()} is required.
  *
  * @return void
  */
 private function auto_update_weights()
 {
     global $CFG;
     if ($this->aggregation != GRADE_AGGREGATE_SUM) {
         // This is only required if we are using natural weights.
         return;
     }
     $children = $this->get_children();
     $gradeitem = null;
     // Calculate the sum of the grademax's of all the items within this category.
     $totalnonoverriddengrademax = 0;
     $totalgrademax = 0;
     // Out of 1, how much weight has been manually overriden by a user?
     $totaloverriddenweight = 0;
     $totaloverriddengrademax = 0;
     // Has every assessment in this category been overridden?
     $automaticgradeitemspresent = false;
     // Does the grade item require normalising?
     $requiresnormalising = false;
     // This array keeps track of the id and weight of every grade item that has been overridden.
     $overridearray = array();
     foreach ($children as $sortorder => $child) {
         $gradeitem = null;
         if ($child['type'] == 'item') {
             $gradeitem = $child['object'];
         } else {
             if ($child['type'] == 'category') {
                 $gradeitem = $child['object']->load_grade_item();
             }
         }
         if ($gradeitem->gradetype == GRADE_TYPE_NONE || $gradeitem->gradetype == GRADE_TYPE_TEXT) {
             // Text items and none items do not have a weight.
             continue;
         } else {
             if (!$this->aggregateoutcomes && $gradeitem->is_outcome_item()) {
                 // We will not aggregate outcome items, so we can ignore them.
                 continue;
             } else {
                 if (empty($CFG->grade_includescalesinaggregation) && $gradeitem->gradetype == GRADE_TYPE_SCALE) {
                     // The scales are not included in the aggregation, ignore them.
                     continue;
                 }
             }
         }
         // Record the ID and the weight for this grade item.
         $overridearray[$gradeitem->id] = array();
         $overridearray[$gradeitem->id]['extracredit'] = intval($gradeitem->aggregationcoef);
         $overridearray[$gradeitem->id]['weight'] = $gradeitem->aggregationcoef2;
         $overridearray[$gradeitem->id]['weightoverride'] = intval($gradeitem->weightoverride);
         // If this item has had its weight overridden then set the flag to true, but
         // only if all previous items were also overridden. Note that extra credit items
         // are counted as overridden grade items.
         if (!$gradeitem->weightoverride && $gradeitem->aggregationcoef == 0) {
             $automaticgradeitemspresent = true;
         }
         if ($gradeitem->aggregationcoef > 0) {
             // An extra credit grade item doesn't contribute to $totaloverriddengrademax.
             continue;
         } else {
             if ($gradeitem->weightoverride > 0 && $gradeitem->aggregationcoef2 <= 0) {
                 // An overriden item that defines a weight of 0 does not contribute to $totaloverriddengrademax.
                 continue;
             }
         }
         $totalgrademax += $gradeitem->grademax;
         if ($gradeitem->weightoverride > 0) {
             $totaloverriddenweight += $gradeitem->aggregationcoef2;
             $totaloverriddengrademax += $gradeitem->grademax;
         }
     }
     // Initialise this variable (used to keep track of the weight override total).
     $normalisetotal = 0;
     // Keep a record of how much the override total is to see if it is above 100. It it is then we need to set the
     // other weights to zero and normalise the others.
     $overriddentotal = 0;
     // If the overridden weight total is higher than 1 then set the other untouched weights to zero.
     $setotherweightstozero = false;
     // Total up all of the weights.
     foreach ($overridearray as $gradeitemdetail) {
         // If the grade item has extra credit, then don't add it to the normalisetotal.
         if (!$gradeitemdetail['extracredit']) {
             $normalisetotal += $gradeitemdetail['weight'];
         }
         // The overridden total comprises of items that are set as overridden, that aren't extra credit and have a value
         // greater than zero.
         if ($gradeitemdetail['weightoverride'] && !$gradeitemdetail['extracredit'] && $gradeitemdetail['weight'] > 0) {
             // Add overriden weights up to see if they are greater than 1.
             $overriddentotal += $gradeitemdetail['weight'];
         }
     }
     if ($overriddentotal > 1) {
         // Make sure that this catergory of weights gets normalised.
         $requiresnormalising = true;
         // The normalised weights are only the overridden weights, so we just use the total of those.
         $normalisetotal = $overriddentotal;
     }
     $totalnonoverriddengrademax = $totalgrademax - $totaloverriddengrademax;
     // This setting indicates if we should use algorithm prior to MDL-49257 fix for calculating extra credit weights.
     // Even though old algorith has bugs in it, we need to preserve existing grades.
     $gradebookcalculationfreeze = (int) get_config('core', 'gradebook_calculations_freeze_' . $this->courseid);
     $oldextracreditcalculation = $gradebookcalculationfreeze && $gradebookcalculationfreeze <= 20150619;
     reset($children);
     foreach ($children as $sortorder => $child) {
         $gradeitem = null;
         if ($child['type'] == 'item') {
             $gradeitem = $child['object'];
         } else {
             if ($child['type'] == 'category') {
                 $gradeitem = $child['object']->load_grade_item();
             }
         }
         if ($gradeitem->gradetype == GRADE_TYPE_NONE || $gradeitem->gradetype == GRADE_TYPE_TEXT) {
             // Text items and none items do not have a weight, no need to set their weight to
             // zero as they must never be used during aggregation.
             continue;
         } else {
             if (!$this->aggregateoutcomes && $gradeitem->is_outcome_item()) {
                 // We will not aggregate outcome items, so we can ignore updating their weights.
                 continue;
             } else {
                 if (empty($CFG->grade_includescalesinaggregation) && $gradeitem->gradetype == GRADE_TYPE_SCALE) {
                     // We will not aggregate the scales, so we can ignore upating their weights.
                     continue;
                 } else {
                     if (!$oldextracreditcalculation && $gradeitem->aggregationcoef > 0 && $gradeitem->weightoverride) {
                         // For an item with extra credit ignore other weigths and overrides but do not change anything at all
                         // if it's weight was already overridden.
                         continue;
                     }
                 }
             }
         }
         // Store the previous value here, no need to update if it is the same value.
         $prevaggregationcoef2 = $gradeitem->aggregationcoef2;
         if (!$oldextracreditcalculation && $gradeitem->aggregationcoef > 0 && !$gradeitem->weightoverride) {
             // For an item with extra credit ignore other weigths and overrides.
             $gradeitem->aggregationcoef2 = $totalgrademax ? $gradeitem->grademax / $totalgrademax : 0;
         } else {
             if (!$gradeitem->weightoverride) {
                 // Calculations with a grade maximum of zero will cause problems. Just set the weight to zero.
                 if ($totaloverriddenweight >= 1 || $totalnonoverriddengrademax == 0 || $gradeitem->grademax == 0) {
                     // There is no more weight to distribute.
                     $gradeitem->aggregationcoef2 = 0;
                 } else {
                     // Calculate this item's weight as a percentage of the non-overridden total grade maxes
                     // then convert it to a proportion of the available non-overriden weight.
                     $gradeitem->aggregationcoef2 = $gradeitem->grademax / $totalnonoverriddengrademax * (1 - $totaloverriddenweight);
                 }
             } else {
                 if (!$automaticgradeitemspresent && $normalisetotal != 1 || $requiresnormalising || $overridearray[$gradeitem->id]['weight'] < 0) {
                     // Just divide the overriden weight for this item against the total weight override of all
                     // items in this category.
                     if ($normalisetotal == 0 || $overridearray[$gradeitem->id]['weight'] < 0) {
                         // If the normalised total equals zero, or the weight value is less than zero,
                         // set the weight for the grade item to zero.
                         $gradeitem->aggregationcoef2 = 0;
                     } else {
                         $gradeitem->aggregationcoef2 = $overridearray[$gradeitem->id]['weight'] / $normalisetotal;
                     }
                 }
             }
         }
         if (grade_floatval($prevaggregationcoef2) !== grade_floatval($gradeitem->aggregationcoef2)) {
             // Update the grade item to reflect these changes.
             $gradeitem->update();
         }
     }
 }
예제 #10
0
 public function test_calculate_peer_grade_two_scales_weighted()
 {
     global $DB;
     // fixture set-up
     $mockscale13 = 'Poor,Good,Excellent';
     $mockscale17 = '-,*,**,***,****,*****,******';
     $this->strategy->dimensions[1012] = (object) array('grade' => '-13', 'weight' => 2);
     $this->strategy->dimensions[1019] = (object) array('grade' => '-17', 'weight' => 3);
     $grades[] = (object) array('dimensionid' => 1012, 'grade' => '2.00000');
     // "Good"
     $grades[] = (object) array('dimensionid' => 1019, 'grade' => '5.00000');
     // "****"
     $DB->expectAt(0, 'get_field', array('scale', 'scale', array('id' => 13), MUST_EXIST));
     $DB->setReturnValueAt(0, 'get_field', $mockscale13);
     $DB->expectAt(1, 'get_field', array('scale', 'scale', array('id' => 17), MUST_EXIST));
     $DB->setReturnValueAt(1, 'get_field', $mockscale17);
     // exercise SUT
     $suggested = $this->strategy->calculate_peer_grade($grades);
     // validate
     $this->assertEqual(grade_floatval((1 / 2 * 2 + 4 / 6 * 3) / 5 * 100), $suggested);
 }
예제 #11
0
/**
 * Check if there are some legacy workshop 1.x data to be migrated and upgrade them
 *
 * This must be called after workshop core migration has finished so that
 * all assessments are already upgraded and tables are correctly renamed.
 */
function workshopform_numerrors_upgrade_legacy() {
    global $CFG, $DB, $OUTPUT;
    require_once($CFG->dirroot . '/mod/workshop/db/upgradelib.php');

    if (!workshopform_numerrors_upgrade_legacy_needed()) {
        return;
    }

    // get the list of all legacy workshops using this grading strategy
    if ($legacyworkshops = $DB->get_records('workshop_old', array('gradingstrategy' => 2), 'course,id', 'id')) {
        echo $OUTPUT->notification('Copying assessment forms elements and grade mappings', 'notifysuccess');
        $legacyworkshops = array_keys($legacyworkshops);
        // get some needed info about the workshops
        $workshopinfos = $DB->get_records_list('workshop_old', 'id', $legacyworkshops, 'id', 'id,grade');
        // get the list of all form elements
        list($workshopids, $params) = $DB->get_in_or_equal($legacyworkshops, SQL_PARAMS_NAMED);
        $sql = "SELECT *
                  FROM {workshop_elements_old}
                 WHERE workshopid $workshopids
                       AND newid IS NULL";
        $rs = $DB->get_recordset_sql($sql, $params);
        foreach ($rs as $old) {
            // process the information about mapping
            $newmapping = new stdclass();
            $newmapping->workshopid = $old->workshopid;
            $newmapping->nonegative = $old->elementno;
            $newmapping->grade = $old->maxscore;
            if ($old->maxscore > 0) {
                $newmapping->grade = grade_floatval($old->maxscore / $workshopinfos[$old->workshopid]->grade * 100);
            } else {
                $newmapping->grade = 0;
            }
            $DB->delete_records('workshopform_numerrors_map',
                                array('workshopid' => $newmapping->workshopid, 'nonegative' => $newmapping->nonegative));
            $DB->insert_record('workshopform_numerrors_map', $newmapping);
            // process the information about the element itself
            if (trim($old->description) and $old->description <> '@@ GRADE_MAPPING_ELEMENT @@') {
                $new = workshopform_numerrors_upgrade_element($old, $old->workshopid);
                $newid = $DB->insert_record('workshopform_numerrors', $new);
            } else {
                $newid = 0;
            }
            $DB->set_field('workshop_elements_old', 'newplugin', 'numerrors', array('id' => $old->id));
            $DB->set_field('workshop_elements_old', 'newid', $newid, array('id' => $old->id));
        }
        $rs->close();

        // now we need to reload the legacy ids. Although we have them in $newelements after the first run, we must
        // refetch them from DB so that this function can be called during recovery
        $newelementids = workshop_upgrade_element_id_mappings('numerrors');

        // migrate all grades for these elements (it est the values that reviewers put into forms)
        echo $OUTPUT->notification('Copying assessment form grades', 'notifysuccess');
        $sql = "SELECT *
                  FROM {workshop_grades_old}
                 WHERE workshopid $workshopids
                       AND newid IS NULL";
        $rs = $DB->get_recordset_sql($sql, $params);
        $newassessmentids = workshop_upgrade_assessment_id_mappings();
        foreach ($rs as $old) {
            if (!isset($newassessmentids[$old->assessmentid])) {
                // orphaned grade - the assessment was removed but the grade remained
                continue;
            }
            if (!isset($newelementids[$old->workshopid]) or !isset($newelementids[$old->workshopid][$old->elementno])) {
                // orphaned grade - the assessment form element has been removed after the grade was recorded
                continue;
            }
            $newelementinfo = $newelementids[$old->workshopid][$old->elementno];
            if ($newelementinfo->newid == 0 or $old->feedback == '@@ GRADE_ADJUSTMENT @@') {
                // this is not a real grade - it was used just for mapping purposes
                $DB->set_field('workshop_grades_old', 'newplugin', 'numerrors_map', array('id' => $old->id));
                $DB->set_field('workshop_grades_old', 'newid', 0, array('id' => $old->id));
                continue;
            }
            $new = workshopform_numerrors_upgrade_grade($old, $newassessmentids[$old->assessmentid],
                                                         $newelementids[$old->workshopid][$old->elementno]);
            $newid = $DB->insert_record('workshop_grades', $new);
            $DB->set_field('workshop_grades_old', 'newplugin', 'numerrors', array('id' => $old->id));
            $DB->set_field('workshop_grades_old', 'newid', $newid, array('id' => $old->id));
        }
        $rs->close();
    }
}
예제 #12
0
파일: lib.php 프로젝트: JP-Git/moodle
 private function normalize_grade($dim,$grade) {
     //todo: weight? is weight a factor here? probably should be...
     $dimmin = $dim->min;
     $dimmax = $dim->max;
     if ($dimmin == $dimmax) {
         return grade_floatval($dimmax);
     } else {
         return grade_floatval(($grade - $dimmin) / ($dimmax - $dimmin) * 100);
     }
 }
예제 #13
0
파일: lib.php 프로젝트: JP-Git/moodle
/**
 * Update workshop grades in the gradebook
 *
 * Needed by grade_update_mod_grades() in lib/gradelib.php
 *
 * @category grade
 * @param stdClass $workshop instance object with extra cmidnumber and modname property
 * @param int $userid        update grade of specific user only, 0 means all participants
 * @return void
 */
function workshop_update_grades(stdclass $workshop, $userid=0) {
    global $CFG, $DB;
    require_once($CFG->libdir.'/gradelib.php');

    //todo: this ignores userid
    if($workshop->teammode) {
        //this is necessary because we need data like the grouping id
        $course     = $DB->get_record('course', array('id' => $workshop->course), '*', MUST_EXIST);
        $cm         = get_coursemodule_from_instance('workshop', $workshop->id, $course->id, false, MUST_EXIST);
        $whereuser  = '';
        if ($userid) {
            $groups = groups_get_all_groups($cm->course, $userid, $cm->groupingid);
            if(count($groups) ==  1) $group = $groups[0];
            $whereuser = $DB->get_in_or_equal(array_keys(groups_get_members($group,'u.id','')));
        } else {
            $allgroups = groups_get_all_groups($cm->course, 0, $cm->groupingid);
            //todo: on duplicate key error out
            $groupmembers = $DB->get_records_list('groups_members','groupid',array_keys($allgroups),'','userid,groupid');
            //invert this array for use later
            $membergroups = array();
            foreach($groupmembers as $i) {
                $membergroups[$i->groupid][] = $i->userid;
            }
        }
        
        $params = array('workshopid' => $workshop->id, 'userid' => $userid);
        $sql = 'SELECT authorid, grade, gradeover, gradeoverby, feedbackauthor, feedbackauthorformat, timemodified, timegraded
                  FROM {workshop_submissions}
                 WHERE workshopid = :workshopid AND example=0' . $whereuser . ' ORDER BY timemodified DESC';

        $records = $DB->get_records_sql($sql, $params);
        $submissions = array();
        
        //this hinges on ORDER BY timemodified DESC
        if ( isset($allgroups) ) {
            foreach($records as $r) {
                $grp = $groupmembers[$r->authorid]->groupid;
                if (isset($submissions[$grp])) continue;
                $submissions[$grp] = $r;
            }
        }
        
//        print_r($submissions);
        
        
        foreach($submissions as $grp => $s) {
            $members = $membergroups[$grp];
            foreach($members as $m) {
                $grade = new stdclass();
                $grade->userid = $m;
                if (!is_null($s->gradeover)) {
                    $grade->rawgrade = grade_floatval($workshop->grade * $s->gradeover / 100);
                    $grade->usermodified = $s->gradeoverby;
                } else {
                    $grade->rawgrade = grade_floatval($workshop->grade * $s->grade / 100);
                }
                $grade->feedback = $s->feedbackauthor;
                $grade->feedbackformat = $s->feedbackauthorformat;
                $grade->datesubmitted = $s->timemodified;
                $grade->dategraded = $s->timegraded;
                $submissiongrades[$m] = $grade;
            }
        }
    } else {
        $whereuser = $userid ? ' AND authorid = :userid' : '';
        $params = array('workshopid' => $workshop->id, 'userid' => $userid);
        $sql = 'SELECT authorid, grade, gradeover, gradeoverby, feedbackauthor, feedbackauthorformat, timemodified, timegraded
                  FROM {workshop_submissions}
                 WHERE workshopid = :workshopid AND example=0' . $whereuser;
        $records = $DB->get_records_sql($sql, $params);
        $submissiongrades = array();
        foreach ($records as $record) {
            $grade = new stdclass();
            $grade->userid = $record->authorid;
            if (!is_null($record->gradeover)) {
                $grade->rawgrade = grade_floatval($workshop->grade * $record->gradeover / 100);
                $grade->usermodified = $record->gradeoverby;
            } else {
                $grade->rawgrade = grade_floatval($workshop->grade * $record->grade / 100);
            }
            $grade->feedback = $record->feedbackauthor;
            $grade->feedbackformat = $record->feedbackauthorformat;
            $grade->datesubmitted = $record->timemodified;
            $grade->dategraded = $record->timegraded;
            $submissiongrades[$record->authorid] = $grade;
        }
    }

    $whereuser = $userid ? ' AND userid = :userid' : '';
    $params = array('workshopid' => $workshop->id, 'userid' => $userid);
    $sql = 'SELECT userid, gradinggrade, timegraded
              FROM {workshop_aggregations}
             WHERE workshopid = :workshopid' . $whereuser;
    $records = $DB->get_records_sql($sql, $params);
    $assessmentgrades = array();
    foreach ($records as $record) {
        $grade = new stdclass();
        $grade->userid = $record->userid;
        $grade->rawgrade = grade_floatval($workshop->gradinggrade * $record->gradinggrade / 100);
        $grade->dategraded = $record->timegraded;
        $assessmentgrades[$record->userid] = $grade;
    }

    workshop_grade_item_update($workshop, $submissiongrades, $assessmentgrades);
}
예제 #14
0
 /**
  * In addition to update() as defined in grade_object rounds the float numbers using php function,
  * the reason is we need to compare the db value with computed number to skip updates if possible.
  *
  * @param string $source from where was the object inserted (mod/forum, manual, etc.)
  * @return bool success
  */
 public function update($source = null)
 {
     $this->rawgrade = grade_floatval($this->rawgrade);
     $this->finalgrade = grade_floatval($this->finalgrade);
     $this->rawgrademin = grade_floatval($this->rawgrademin);
     $this->rawgrademax = grade_floatval($this->rawgrademax);
     return parent::update($source);
 }
예제 #15
0
 public function test_average_assessment_different_weights()
 {
     // fixture set-up
     $assessments = array();
     $assessments[11] = (object) array('weight' => 1, 'dimgrades' => array(3 => 10.0, 4 => 13.4, 5 => 95.0));
     $assessments[13] = (object) array('weight' => 3, 'dimgrades' => array(3 => 11.0, 4 => 10.1, 5 => 92.0));
     $assessments[17] = (object) array('weight' => 1, 'dimgrades' => array(3 => 11.0, 4 => 8.1, 5 => 88.0));
     // exercise SUT
     $average = $this->evaluator->average_assessment($assessments);
     // validate
     $this->assertEquals(gettype($average->dimgrades), 'array');
     $this->assertEquals(grade_floatval($average->dimgrades[3]), grade_floatval((10.0 + 11.0 * 3 + 11.0) / 5));
     $this->assertEquals(grade_floatval($average->dimgrades[4]), grade_floatval((13.4 + 10.1 * 3 + 8.1) / 5));
     $this->assertEquals(grade_floatval($average->dimgrades[5]), grade_floatval((95.0 + 92.0 * 3 + 88.0) / 5));
 }
예제 #16
0
파일: lib.php 프로젝트: ncsu-delta/moodle
/**
 * Update workshop grades in the gradebook
 *
 * Needed by grade_update_mod_grades() in lib/gradelib.php
 *
 * @category grade
 * @param stdClass $workshop instance object with extra cmidnumber and modname property
 * @param int $userid        update grade of specific user only, 0 means all participants
 * @return void
 */
function workshop_update_grades(stdclass $workshop, $userid=0) {
    global $CFG, $DB;
    require_once($CFG->libdir.'/gradelib.php');

    $whereuser = $userid ? ' AND authorid = :userid' : '';
    $params = array('workshopid' => $workshop->id, 'userid' => $userid);
    $sql = 'SELECT authorid, grade, gradeover, gradeoverby, feedbackauthor, feedbackauthorformat, timemodified, timegraded
              FROM {workshop_submissions}
             WHERE workshopid = :workshopid AND example=0' . $whereuser;
    $records = $DB->get_records_sql($sql, $params);
    $submissiongrades = array();
    foreach ($records as $record) {
        $grade = new stdclass();
        $grade->userid = $record->authorid;
        if (!is_null($record->gradeover)) {
            $grade->rawgrade = grade_floatval($workshop->grade * $record->gradeover / 100);
            $grade->usermodified = $record->gradeoverby;
        } else {
            $grade->rawgrade = grade_floatval($workshop->grade * $record->grade / 100);
        }
        $grade->feedback = $record->feedbackauthor;
        $grade->feedbackformat = $record->feedbackauthorformat;
        $grade->datesubmitted = $record->timemodified;
        $grade->dategraded = $record->timegraded;
        $submissiongrades[$record->authorid] = $grade;
    }

    $whereuser = $userid ? ' AND userid = :userid' : '';
    $params = array('workshopid' => $workshop->id, 'userid' => $userid);
    $sql = 'SELECT userid, gradinggrade, timegraded
              FROM {workshop_aggregations}
             WHERE workshopid = :workshopid' . $whereuser;
    $records = $DB->get_records_sql($sql, $params);
    $assessmentgrades = array();
    foreach ($records as $record) {
        $grade = new stdclass();
        $grade->userid = $record->userid;
        $grade->rawgrade = grade_floatval($workshop->gradinggrade * $record->gradinggrade / 100);
        $grade->dategraded = $record->timegraded;
        $assessmentgrades[$record->userid] = $grade;
    }

    workshop_grade_item_update($workshop, $submissiongrades, $assessmentgrades);
}
예제 #17
0
/**
 * Given a record from workshop_assessments_old, returns record to be stored in workshop_assessment
 *
 * @param stdClass $old                 record from workshop_assessments_old,
 * @param int      $newsubmissionid     new submission id
 * @param array    $legacyteachers      (int)userid => notused the list of legacy workshop teachers for the submission's workshop
 * @param int      $legacyteacherweight weight of teacher's assessment in legacy workshop
 * @return stdClass
 */
function workshop_upgrade_transform_assessment(stdClass $old, $newsubmissionid, array $legacyteachers, $legacyteacherweight)
{
    global $CFG;
    require_once $CFG->libdir . '/gradelib.php';
    $new = new stdclass();
    $new->submissionid = $newsubmissionid;
    $new->reviewerid = $old->userid;
    if (isset($legacyteachers[$old->userid])) {
        $new->weight = $legacyteacherweight;
    } else {
        $new->weight = 1;
    }
    if ($old->grade < 0) {
        // in workshop 1.x, this is just allocated assessment that has not been touched yet, having timecreated one year in the future :-/
        $new->timecreated = time();
    } else {
        $new->grade = grade_floatval($old->grade);
        if ($old->teachergraded) {
            $new->gradinggradeover = grade_floatval($old->gradinggrade);
        } else {
            $new->gradinggrade = grade_floatval($old->gradinggrade);
        }
        $new->feedbackauthor = $old->generalcomment;
        $new->feedbackauthorformat = FORMAT_HTML;
        $new->feedbackreviewer = $old->teachercomment;
        $new->feedbackreviewerformat = FORMAT_HTML;
        $new->timecreated = $old->timecreated;
        $new->timemodified = $old->timegraded;
    }
    return $new;
}
예제 #18
0
파일: lib.php 프로젝트: JP-Git/moodle
    /**
     * Given a set of a submission's assessments, returns a hypothetical average assessment
     *
     * The passed structure must be array of assessments objects with ->weight and ->dimgrades properties.
     *
     * @param array $assessments as prepared by {@link self::prepare_data_from_recordset()}
     * @return null|stdClass
     */
    protected function average_assessment(array $assessments) {
        $sumdimgrades = array();
        foreach ($assessments as $a) {
            foreach ($a->dimgrades as $dimid => $dimgrade) {
                if (!isset($sumdimgrades[$dimid])) {
                    $sumdimgrades[$dimid] = 0;
                }
                $sumdimgrades[$dimid] += $dimgrade * $a->weight;
            }
        }

        $sumweights = 0;
        foreach ($assessments as $a) {
            $sumweights += $a->weight;
        }
        if ($sumweights == 0) {
            // unable to calculate average assessment
            return null;
        }

        $average = new stdclass();
        $average->dimgrades = array();
        foreach ($sumdimgrades as $dimid => $sumdimgrade) {
            $average->dimgrades[$dimid] = grade_floatval($sumdimgrade / $sumweights);
        }
        return $average;
    }
예제 #19
0
파일: mod_form.php 프로젝트: janeklb/moodle
 public function validation($data, $files)
 {
     $errors = parent::validation($data, $files);
     // Check open and close times are consistent.
     if ($data['timeopen'] != 0 && $data['timeclose'] != 0 && $data['timeclose'] < $data['timeopen']) {
         $errors['timeclose'] = get_string('closebeforeopen', 'quiz');
     }
     // Check that the grace period is not too short.
     if ($data['overduehandling'] == 'graceperiod') {
         $graceperiodmin = get_config('quiz', 'graceperiodmin');
         if ($data['graceperiod'] <= $graceperiodmin) {
             $errors['graceperiod'] = get_string('graceperiodtoosmall', 'quiz', format_time($graceperiodmin));
         }
     }
     if (array_key_exists('completion', $data) && $data['completion'] == COMPLETION_TRACKING_AUTOMATIC) {
         $completionpass = isset($data['completionpass']) ? $data['completionpass'] : $this->current->completionpass;
         // Show an error if require passing grade was selected and the grade to pass was set to 0.
         if ($completionpass && (empty($data['gradepass']) || grade_floatval($data['gradepass']) == 0)) {
             if (isset($data['completionpass'])) {
                 $errors['completionpassgroup'] = get_string('gradetopassnotset', 'quiz');
             } else {
                 $errors['gradepass'] = get_string('gradetopassmustbeset', 'quiz');
             }
         }
     }
     // Check the boundary value is a number or a percentage, and in range.
     $i = 0;
     while (!empty($data['feedbackboundaries'][$i])) {
         $boundary = trim($data['feedbackboundaries'][$i]);
         if (strlen($boundary) > 0) {
             if ($boundary[strlen($boundary) - 1] == '%') {
                 $boundary = trim(substr($boundary, 0, -1));
                 if (is_numeric($boundary)) {
                     $boundary = $boundary * $data['grade'] / 100.0;
                 } else {
                     $errors["feedbackboundaries[{$i}]"] = get_string('feedbackerrorboundaryformat', 'quiz', $i + 1);
                 }
             } else {
                 if (!is_numeric($boundary)) {
                     $errors["feedbackboundaries[{$i}]"] = get_string('feedbackerrorboundaryformat', 'quiz', $i + 1);
                 }
             }
         }
         if (is_numeric($boundary) && $boundary <= 0 || $boundary >= $data['grade']) {
             $errors["feedbackboundaries[{$i}]"] = get_string('feedbackerrorboundaryoutofrange', 'quiz', $i + 1);
         }
         if (is_numeric($boundary) && $i > 0 && $boundary >= $data['feedbackboundaries'][$i - 1]) {
             $errors["feedbackboundaries[{$i}]"] = get_string('feedbackerrororder', 'quiz', $i + 1);
         }
         $data['feedbackboundaries'][$i] = $boundary;
         $i += 1;
     }
     $numboundaries = $i;
     // Check there is nothing in the remaining unused fields.
     if (!empty($data['feedbackboundaries'])) {
         for ($i = $numboundaries; $i < count($data['feedbackboundaries']); $i += 1) {
             if (!empty($data['feedbackboundaries'][$i]) && trim($data['feedbackboundaries'][$i]) != '') {
                 $errors["feedbackboundaries[{$i}]"] = get_string('feedbackerrorjunkinboundary', 'quiz', $i + 1);
             }
         }
     }
     for ($i = $numboundaries + 1; $i < count($data['feedbacktext']); $i += 1) {
         if (!empty($data['feedbacktext'][$i]['text']) && trim($data['feedbacktext'][$i]['text']) != '') {
             $errors["feedbacktext[{$i}]"] = get_string('feedbackerrorjunkinfeedback', 'quiz', $i + 1);
         }
     }
     // Any other rule plugins.
     $errors = quiz_access_manager::validate_settings_form_fields($errors, $data, $files, $this);
     return $errors;
 }
예제 #20
0
/**
 * Compare two float numbers safely. Uses 5 decimals php precision using {@link grade_floatval()}
 *
 * Do not use rounding for 10,5 at the database level as the results may be
 * different from php round() function.
 *
 * @since 2.0
 * @param float $f1 Float one to compare
 * @param float $f2 Float two to compare
 * @return bool True if the values should be considered as the same grades
 */
function grade_floats_equal($f1, $f2)
{
    return grade_floatval($f1) === grade_floatval($f2);
}
예제 #21
0
 /**
  * save grade
  *
  * @param  moodleform $mform
  * @return bool - was the grade saved
  */
 private function process_save_grade(&$mform)
 {
     global $USER, $DB, $CFG;
     // Include grade form
     require_once $CFG->dirroot . '/mod/assign/gradeform.php';
     // Need submit permission to submit an assignment
     require_capability('mod/assign:grade', $this->context);
     require_sesskey();
     $rownum = required_param('rownum', PARAM_INT);
     $useridlist = optional_param('useridlist', '', PARAM_TEXT);
     if ($useridlist) {
         $useridlist = explode(',', $useridlist);
     } else {
         $useridlist = $this->get_grading_userid_list();
     }
     $last = false;
     $userid = $useridlist[$rownum];
     if ($rownum == count($useridlist) - 1) {
         $last = true;
     }
     $data = new stdClass();
     $mform = new mod_assign_grade_form(null, array($this, $data, array('rownum' => $rownum, 'useridlist' => $useridlist, 'last' => false)), 'post', '', array('class' => 'gradeform'));
     if ($formdata = $mform->get_data()) {
         $grade = $this->get_user_grade($userid, true);
         $gradingdisabled = $this->grading_disabled($userid);
         $gradinginstance = $this->get_grading_instance($userid, $gradingdisabled);
         if (!$gradingdisabled) {
             if ($gradinginstance) {
                 $grade->grade = $gradinginstance->submit_and_get_grade($formdata->advancedgrading, $grade->id);
             } else {
                 // handle the case when grade is set to No Grade
                 if (isset($formdata->grade)) {
                     $grade->grade = grade_floatval(unformat_float($formdata->grade));
                 }
             }
         }
         $grade->grader = $USER->id;
         $adminconfig = $this->get_admin_config();
         $gradebookplugin = $adminconfig->feedback_plugin_for_gradebook;
         // call save in plugins
         foreach ($this->feedbackplugins as $plugin) {
             if ($plugin->is_enabled() && $plugin->is_visible()) {
                 if (!$plugin->save($grade, $formdata)) {
                     $result = false;
                     print_error($plugin->get_error());
                 }
                 if ('assignfeedback_' . $plugin->get_type() == $gradebookplugin) {
                     // this is the feedback plugin chose to push comments to the gradebook
                     $grade->feedbacktext = $plugin->text_for_gradebook($grade);
                     $grade->feedbackformat = $plugin->format_for_gradebook($grade);
                 }
             }
         }
         $this->process_outcomes($userid, $formdata);
         $grade->mailed = 0;
         $this->update_grade($grade);
         $this->notify_grade_modified($grade);
         $user = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST);
         $this->add_to_log('grade submission', $this->format_grade_for_log($grade));
     } else {
         return false;
     }
     return true;
 }
예제 #22
0
 /**
  * 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)
  * @param null|int $timegraded explicit timestamp of the aggregation, defaults to the current time
  * @return void
  */
 protected function aggregate_grading_grades_process(array $assessments, $timegraded = null)
 {
     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;
     if (is_null($timegraded)) {
         $timegraded = time();
     }
     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 overridden 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);
     }
     // Event information.
     $params = array('context' => $this->context, 'courseid' => $this->course->id, 'relateduserid' => $reviewerid);
     // check if the new final grade differs from the one stored in the database
     if (grade_floats_different($finalgrade, $current)) {
         $params['other'] = array('currentgrade' => $current, 'finalgrade' => $finalgrade);
         // 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;
             $record->timegraded = $timegraded;
             $record->id = $DB->insert_record('workshop_aggregations', $record);
             $params['objectid'] = $record->id;
             $event = \mod_workshop\event\assessment_evaluated::create($params);
             $event->trigger();
         } else {
             $record = new stdclass();
             $record->id = $agid;
             $record->gradinggrade = $finalgrade;
             $record->timegraded = $timegraded;
             $DB->update_record('workshop_aggregations', $record);
             $params['objectid'] = $agid;
             $event = \mod_workshop\event\assessment_reevaluated::create($params);
             $event->trigger();
         }
     }
 }
예제 #23
0
파일: locallib.php 프로젝트: verbazend/AWFA
    /**
     * Apply a grade from a grading form to a user (may be called multiple times for a group submission).
     *
     * @param stdClass $formdata - the data from the form
     * @param int $userid - the user to apply the grade to
     * @param int attemptnumber - The attempt number to apply the grade to.
     * @return void
     */
    protected function apply_grade_to_user($formdata, $userid, $attemptnumber) {
        global $USER, $CFG, $DB;

        $grade = $this->get_user_grade($userid, true, $attemptnumber);
        $gradingdisabled = $this->grading_disabled($userid);
        $gradinginstance = $this->get_grading_instance($userid, $grade, $gradingdisabled);
        if (!$gradingdisabled) {
            if ($gradinginstance) {
                $grade->grade = $gradinginstance->submit_and_get_grade($formdata->advancedgrading,
                                                                       $grade->id);
            } else {
                // Handle the case when grade is set to No Grade.
                if (isset($formdata->grade)) {
                    $grade->grade = grade_floatval(unformat_float($formdata->grade));
                }
            }
        }
        $grade->grader= $USER->id;

        $adminconfig = $this->get_admin_config();
        $gradebookplugin = $adminconfig->feedback_plugin_for_gradebook;

        // Call save in plugins.
        foreach ($this->feedbackplugins as $plugin) {
            if ($plugin->is_enabled() && $plugin->is_visible()) {
                if (!$plugin->save($grade, $formdata)) {
                    $result = false;
                    print_error($plugin->get_error());
                }
                if (('assignfeedback_' . $plugin->get_type()) == $gradebookplugin) {
                    // This is the feedback plugin chose to push comments to the gradebook.
                    $grade->feedbacktext = $plugin->text_for_gradebook($grade);
                    $grade->feedbackformat = $plugin->format_for_gradebook($grade);
                }
            }
        }
        $this->update_grade($grade);
        // Note the default if not provided for this option is true (e.g. webservices).
        // This is for backwards compatibility.
        if (!isset($formdata->sendstudentnotifications) || $formdata->sendstudentnotifications) {
            $this->notify_grade_modified($grade);
        }

        $this->add_to_log('grade submission', $this->format_grade_for_log($grade));
    }
예제 #24
0
 /**
  * Apply a grade from a grading form to a user (may be called multiple times for a group submission).
  *
  * @param stdClass $formdata - the data from the form
  * @param int $userid - the user to apply the grade to
  * @param int $attemptnumber - The attempt number to apply the grade to.
  * @return void
  */
 protected function apply_grade_to_user($formdata, $userid, $attemptnumber)
 {
     global $USER, $CFG, $DB;
     $grade = $this->get_user_grade($userid, true, $attemptnumber);
     $originalgrade = $grade->grade;
     $gradingdisabled = $this->grading_disabled($userid);
     $gradinginstance = $this->get_grading_instance($userid, $grade, $gradingdisabled);
     if (!$gradingdisabled) {
         if ($gradinginstance) {
             $grade->grade = $gradinginstance->submit_and_get_grade($formdata->advancedgrading, $grade->id);
         } else {
             // Handle the case when grade is set to No Grade.
             if (isset($formdata->grade)) {
                 $grade->grade = grade_floatval(unformat_float($formdata->grade));
             }
         }
         if (isset($formdata->workflowstate) || isset($formdata->allocatedmarker)) {
             $flags = $this->get_user_flags($userid, true);
             $oldworkflowstate = $flags->workflowstate;
             $flags->workflowstate = isset($formdata->workflowstate) ? $formdata->workflowstate : $flags->workflowstate;
             $flags->allocatedmarker = isset($formdata->allocatedmarker) ? $formdata->allocatedmarker : $flags->allocatedmarker;
             if ($this->update_user_flags($flags) && isset($formdata->workflowstate) && $formdata->workflowstate !== $oldworkflowstate) {
                 $user = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST);
                 \mod_assign\event\workflow_state_updated::create_from_user($this, $user, $formdata->workflowstate)->trigger();
             }
         }
     }
     $grade->grader = $USER->id;
     $adminconfig = $this->get_admin_config();
     $gradebookplugin = $adminconfig->feedback_plugin_for_gradebook;
     // Call save in plugins.
     foreach ($this->feedbackplugins as $plugin) {
         if ($plugin->is_enabled() && $plugin->is_visible()) {
             if (!$plugin->save($grade, $formdata)) {
                 $result = false;
                 print_error($plugin->get_error());
             }
             if ('assignfeedback_' . $plugin->get_type() == $gradebookplugin) {
                 // This is the feedback plugin chose to push comments to the gradebook.
                 $grade->feedbacktext = $plugin->text_for_gradebook($grade);
                 $grade->feedbackformat = $plugin->format_for_gradebook($grade);
             }
         }
     }
     // We do not want to update the timemodified if no grade was added.
     if (!empty($formdata->addattempt) || $originalgrade !== null && $originalgrade != -1 || $grade->grade !== null && $grade->grade != -1) {
         $this->update_grade($grade, !empty($formdata->addattempt));
     }
     // Note the default if not provided for this option is true (e.g. webservices).
     // This is for backwards compatibility.
     if (!isset($formdata->sendstudentnotifications) || $formdata->sendstudentnotifications) {
         $this->notify_grade_modified($grade, true);
     }
 }
예제 #25
0
파일: lib_test.php 프로젝트: evltuma/moodle
 public function test_calculate_peer_grade_something()
 {
     // fixture set-up
     $grades[6] = (object) array('dimensionid' => 6, 'grade' => 2);
     $grades[8] = (object) array('dimensionid' => 8, 'grade' => 2);
     $grades[10] = (object) array('dimensionid' => 10, 'grade' => 30);
     // exercise SUT
     $suggested = $this->strategy->calculate_peer_grade($grades);
     // validate
     // minimal rubric score is 10, maximal is 51. We have 34 here
     $this->assertEquals(grade_floatval($suggested), grade_floatval(100 * 24 / 41));
 }
예제 #26
0
파일: locallib.php 프로젝트: nuckey/moodle
    /**
     * 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 void
     */
    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 overridden 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;
                $record->timegraded = time();
                $DB->insert_record('workshop_aggregations', $record);
            } else {
                $record = new stdclass();
                $record->id = $agid;
                $record->gradinggrade = $finalgrade;
                $record->timegraded = time();
                $DB->update_record('workshop_aggregations', $record);
            }
        }
    }
예제 #27
0
/**
 * Update workshopplus grades in the gradebook
 *
 * Needed by grade_update_mod_grades() in lib/gradelib.php
 *
 * @category grade
 * @param stdClass $workshopplus instance object with extra cmidnumber and modname property
 * @param int $userid        update grade of specific user only, 0 means all participants
 * @return void
 */
function workshopplus_update_grades(stdclass $workshopplus, $userid = 0)
{
    global $CFG, $DB;
    require_once $CFG->libdir . '/gradelib.php';
    $whereuser = $userid ? ' AND authorid = :userid' : '';
    $params = array('workshopplusid' => $workshopplus->id, 'userid' => $userid);
    $sql = 'SELECT authorid, grade, gradeover, gradeoverby, feedbackauthor, feedbackauthorformat, timemodified, timegraded
              FROM {workshopplus_submissions}
             WHERE workshopplusid = :workshopplusid AND example=0' . $whereuser;
    $records = $DB->get_records_sql($sql, $params);
    $submissiongrades = array();
    foreach ($records as $record) {
        $grade = new stdclass();
        $grade->userid = $record->authorid;
        if (!is_null($record->gradeover)) {
            $grade->rawgrade = grade_floatval($workshopplus->grade * $record->gradeover / 100);
            $grade->usermodified = $record->gradeoverby;
        } else {
            $grade->rawgrade = grade_floatval($workshopplus->grade * $record->grade / 100);
        }
        $grade->feedback = $record->feedbackauthor;
        $grade->feedbackformat = $record->feedbackauthorformat;
        $grade->datesubmitted = $record->timemodified;
        $grade->dategraded = $record->timegraded;
        $submissiongrades[$record->authorid] = $grade;
        ////// Find the groupmates and also update their records
        ////////////By Morteza
        /// find the group id of the current user
        $usergroups = groups_get_user_groups($workshopplus->course, $grade->userid);
        $currentgroupid = $usergroups[0][0];
        // Get the current group name from the group id.
        $currentgroupname = groups_get_group_name($currentgroupid);
        // loop over members of that group
        $groupmembers = groups_get_members($currentgroupid, $fields = 'u.*');
        /* Commenting out section for blind copy of grades
            * -- Sayantan - 28.04.2015
           foreach ($groupmembers as $memberid=>$member){                    
               if ($memberid != $grade->userid) {
                   $newgrade = clone $grade;
                   $newgrade->userid = $memberid;
                   $submissiongrades[$memberid] = $newgrade;
               }
           }
           */
        //////////end by Morteza
        /*
         * Begin: Change by Sayantan
         * Date: 28.04.2015
         */
        // Also think of scenario where author belonged to another group - Not possible unless students are
        // allowed to resubmit their solutions - have to think about this one
        // Check if this assignment has been graded previously (entry exists in grade_grades)
        //      no -> this is a new grading, simply copy grade of author to the group members
        //      yes -> this is a regrading
        $params = array('workshopplusid' => $workshopplus->id, 'userid' => $grade->userid);
        $sql = 'SELECT COUNT(1) AS cnt FROM moodle_grade_grades grades ' . 'INNER JOIN moodle_grade_items items ' . 'WHERE items.id = grades.itemid AND items.iteminstance = :workshopplusid AND grades.userid=:userid';
        $records = $DB->get_records_sql($sql, $params);
        $flag_re_grading = 0;
        foreach ($records as $record) {
            if ($record->cnt > 0) {
                // Check if records exist in grade_grades
                $flag_re_grading = 1;
                // If records exist in grade_grades then this is a regrading
            }
        }
        if ($flag_re_grading == 0) {
            // This is a new grading, hence copy grades
            foreach ($groupmembers as $memberid => $member) {
                if ($memberid != $grade->userid) {
                    $newgrade = clone $grade;
                    $newgrade->userid = $memberid;
                    $submissiongrades[$memberid] = $newgrade;
                }
            }
        } else {
            // This is a re grading, hence existing grades should not be overwritten
            //          + Check the time in which each member joined the group
            //          + If the time of joining group is later than time of previous grading then member was in a
            //          separate group when the initial grading was done and should get the grades he/she received
            //          in that group
            //          + If the member has no previous records - assign zero grade since this assignment was not
            //          done by that member (as he was not part of any group when the assignment was first graded)
            //
            foreach ($groupmembers as $memberid => $member) {
                if ($memberid != $grade->userid) {
                    // Check time at which $memberid joined the group
                    $joining_time = 0;
                    $params = array('userid' => $memberid);
                    $sql = 'SELECT timeadded FROM moodle_groups_members WHERE userid=:userid';
                    $records = $DB->get_records_sql($sql, $params);
                    foreach ($records as $record) {
                        $joining_time = $record->timeadded;
                    }
                    // Check time of previous grading
                    $grading_modified_time = 0;
                    $params = array('workshopplusid' => $workshopplus->id, 'userid' => $memberid);
                    $sql = 'SELECT grades.timemodified FROM moodle_grade_grades grades INNER JOIN moodle_grade_items items WHERE items.id = grades.itemid AND items.iteminstance=:workshopplusid AND grades.userid=:userid';
                    $records = $DB->get_records_sql($sql, $params);
                    // If no records are fetched then for the particular group member there exist no records in grades
                    // This means that when the previous grading was done this member was not part of any group
                    // and the grade assigned should be 0
                    if (sizeof($records) == 0) {
                        $newgrade = clone $grade;
                        $newgrade->userid = $memberid;
                        $grade->rawgrade = 0;
                        // Grade assigned to zero since this member was not present when previous grading was done
                        $submissiongrades[$memberid] = $newgrade;
                    } else {
                        foreach ($records as $record) {
                            $grading_modified_time = $record->timemodified;
                        }
                    }
                    // If records exist for the member in grades, and time of joining group is before time of previous grading
                    // then a simple copy of grades from the author's grades is okay
                    if (sizeof($records) < 0 && $grading_modified_time > $joining_time) {
                        $newgrade = clone $grade;
                        // Copy grade since member was in authors group earlier also
                        $newgrade->userid = $memberid;
                        $submissiongrades[$memberid] = $newgrade;
                    }
                    // If record exists for the member in grade but time of joining group is after time of last grading
                    // then we need to restore the previous grade that this member achieved
                    if (sizeof($records) < 0 && $grading_modified_time < $joining_time) {
                        // This member has already received a grade for this assignment
                        // but the member was in another group
                        // hence leave the previous grade untouched
                        // do not add this grade in the array $submissiongrades
                        // Thus in the grades table, the old grade for this member will remain unchanged
                        // Need to recalculate grades from the workshopplus submission of previous group
                        // the member belonged to
                        // Check the group history table
                        // Find a group with max(timeadded) < $grading_modified_time
                        $params = array('grading_modified_time' => $grading_modified_time, 'userid' => $memberid);
                        $sql = 'SELECT groupid FROM moodle_groups_members_history a WHERE userid=:userid AND timeadded=(SELECT MAX(timeadded) FROM moodle_groups_members_history b WHERE a.userid=b.userid AND a.groupid=b.groupid AND b.timeadded<:grading_modified_time)';
                        $records = $DB->get_records_sql($sql, $params);
                        // Find members of this group
                        foreach ($records as $record) {
                            $groupid = $records->groupid;
                        }
                        // loop over members of that group
                        $groupmembers = groups_get_members($groupid, $fields = 'u.*');
                        // Iterate over members to find submission for the given workshopplus id
                        foreach ($groupmembers as $oldmemberid => $oldmember) {
                            // Find submission for this group in workshopplus_submissions
                            $oldparams = array('workshopplusid' => $workshopplus->id, 'userid' => $oldmemberid);
                            $oldsql = 'SELECT authorid, grade, gradeover, gradeoverby, feedbackauthor, feedbackauthorformat, timemodified, timegraded FROM {workshopplus_submissions} WHERE workshopplusid = :workshopplusid AND example=0 AND authorid=:userid ORDER BY timemodified DESC';
                            $oldrecords = $DB->get_records_sql($oldsql, $oldparams);
                            // Break whenever a submission is found for a member
                            if (sizeof($records != 0)) {
                                // Copy grade for this user
                                $oldgrade = new stdclass();
                                $oldgrade->userid = $memberid;
                                if (!is_null($oldrecords->gradeover)) {
                                    $oldgrade->rawgrade = grade_floatval($workshopplus->grade * $oldrecords->gradeover / 100);
                                    $oldgrade->usermodified = $oldrecords->gradeoverby;
                                } else {
                                    $oldgrade->rawgrade = grade_floatval($workshopplus->grade * $oldrecords->grade / 100);
                                }
                                $oldgrade->feedback = $oldrecords->feedbackauthor;
                                $oldgrade->feedbackformat = $oldrecords->feedbackauthorformat;
                                $oldgrade->datesubmitted = $oldrecords->timemodified;
                                $oldgrade->dategraded = $oldrecords->timegraded;
                                $submissiongrades[$memberid] = $oldgrade;
                                break;
                            }
                        }
                    }
                }
            }
        }
        /*
         * End: Change by Sayantan
         * Date: 28.04.2015
         */
    }
    // Updating assessment grades -- only comment added -- no change to code
    $whereuser = $userid ? ' AND userid = :userid' : '';
    $params = array('workshopplusid' => $workshopplus->id, 'userid' => $userid);
    $sql = 'SELECT userid, gradinggrade, timegraded
              FROM {workshopplus_aggregations}
             WHERE workshopplusid = :workshopplusid' . $whereuser;
    $records = $DB->get_records_sql($sql, $params);
    $assessmentgrades = array();
    foreach ($records as $record) {
        $grade = new stdclass();
        $grade->userid = $record->userid;
        $grade->rawgrade = grade_floatval($workshopplus->gradinggrade * $record->gradinggrade / 100);
        $grade->dategraded = $record->timegraded;
        $assessmentgrades[$record->userid] = $grade;
    }
    workshopplus_grade_item_update($workshopplus, $submissiongrades, $assessmentgrades);
}
예제 #28
0
 public function test_calculate_peer_grade_two_scales_weighted()
 {
     $this->resetAfterTest(true);
     // fixture set-up
     $scale13 = $this->getDataGenerator()->create_scale(array('scale' => 'Poor,Good,Excellent', 'id' => 13));
     $scale17 = $this->getDataGenerator()->create_scale(array('scale' => '-,*,**,***,****,*****,******', 'id' => 17));
     $this->strategy->dimensions[1012] = (object) array('grade' => -$scale13->id, 'weight' => 2);
     $this->strategy->dimensions[1019] = (object) array('grade' => -$scale17->id, 'weight' => 3);
     $grades[] = (object) array('dimensionid' => 1012, 'grade' => '2.00000');
     // "Good"
     $grades[] = (object) array('dimensionid' => 1019, 'grade' => '5.00000');
     // "****"
     // exercise SUT
     $suggested = $this->strategy->calculate_peer_grade($grades);
     // validate
     $this->assertEquals(grade_floatval((1 / 2 * 2 + 4 / 6 * 3) / 5 * 100), $suggested);
 }
예제 #29
0
 public static function get_final_grade_by_course_id($courseId, $roleId)
 {
     // no MOODLE não temos factories
     // obtemos os acessores diretamente via variaveis globais
     global $CFG;
     require_once $CFG->dirroot . '/grade/lib.php';
     require_once $CFG->dirroot . '/grade/querylib.php';
     require_once $CFG->dirroot . '/user/lib.php';
     // para trabalhar com as grades de notas precisa-se ter
     // as seguintes habilidades:
     // * moodle/grade:export
     // * gradeexprt/txt:view
     // primeiro pego o contexto do sistema com base no usuário corrente
     $context = get_context_instance(CONTEXT_SYSTEM);
     // então verifico as abilidades uma a uma
     require_capability('moodle/grade:export', $context);
     require_capability('gradeexport/txt:view', $context);
     // neste ponto se verifica os parametros informados estão corretos
     // e dentro do exigido pela função
     // observe que solicitei os parametros como sendo do tipo inteiro
     // diretamente sem que sejam algum tipo de estrutura. Isto facilita
     // o acesso aos parametros,
     $funcParams = self::validate_parameters(self::get_final_grade_by_course_id_parameters(), array('courseId' => $courseId, 'roleId' => $roleId));
     if (MDEBUG) {
         mDebug_log($funcParams, 'Parametros da Função');
     }
     $usersIds = array();
     $context = get_context_instance(CONTEXT_COURSE, $funcParams['courseId']);
     $role = new stdClass();
     $role->id = $roleId;
     $users = get_users_from_role_on_context($role, $context);
     if (MDEBUG) {
         mDebug_log($users);
     }
     $usersIds = array();
     foreach ($users as $user) {
         $usersIds[] = $user->userid;
     }
     if (MDEBUG) {
         mDebug_log($usersIds, 'Ids dos Usuários');
     }
     // OK, agora que está tudo ok, consulto no banco de dados a nota
     // do usuário conforme o curso
     $grades = grade_get_course_grades($funcParams['courseId'], $usersIds);
     if (MDEBUG) {
         mDebug_log($grades, 'Grades');
     }
     // TODO, estudar melhorias neste retorno.
     foreach ($grades->grades as $userId => $grade) {
         $result = array();
         if ($grade === false) {
             $result['grade'] = grade_floatval(-9999);
         } else {
             if ($grade === null) {
                 $result['grade'] = grade_floatval(-8888);
             } else {
                 $result['grade'] = grade_floatval($grade->grade);
             }
         }
         $result['userId'] = $userId;
         $results[] = $result;
     }
     if (MDEBUG) {
         mDebug_log($results, 'Grades finais a serem enviadas');
     }
     return $results;
 }