AutorÃa | Ultima modificación | Ver Log |
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace gradepenalty_duedate;
use cm_info;
use context_course;
use context_module;
use context_system;
use core_grades\penalty_container;
/**
* Penalty plugins must override this class to implement their own penalty calculation.
*
* @package gradepenalty_duedate
* @copyright 2024 Catalyst IT Australia Pty Ltd
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class penalty_calculator extends \core_grades\penalty_calculator {
/**
* Calculate the penalty for the given activity.
*
* @param penalty_container $container The penalty container.
*/
public static function calculate_penalty(penalty_container $container): void {
// Calculate the deducted grade based on the max grade.
$gradeitem = $container->get_grade_item();
$modinfo = get_fast_modinfo($gradeitem->courseid);
$cm = $modinfo->instances[$gradeitem->itemmodule][$gradeitem->iteminstance];
$deductedpercentage = self::get_penalty_from_rules($cm, $container->get_submission_date(), $container->get_due_date());
$deductedgrade = $container->get_max_grade() * $deductedpercentage / 100;
$container->aggregate_penalty($deductedgrade);
}
/**
* Get the penalty percentage from the most appropriate penalty rule based on the submission date and the due date.
*
* @param cm_info $cm The course module object.
* @param int $submissiondate The submission date.
* @param int $duedate The due date.
* @return float the deducted percentage.
*/
public static function get_penalty_from_rules(cm_info $cm, int $submissiondate, int $duedate): float {
// Get the difference between the submission date and the due date.
$diff = $submissiondate - $duedate;
// Return if the due date is after the submission date.
if ($diff <= 0) {
return 0;
}
// Get all penalty rules, ordered by the highest penalty first.
$penaltyrules = self::find_effective_penalty_rules($cm);
// Return if there are no penalty rules.
if (empty($penaltyrules)) {
return 0;
}
// Return the first applicable penalty rule.
foreach ($penaltyrules as $penaltyrule) {
if ($diff <= $penaltyrule->get('overdueby')) {
return $penaltyrule->get('penalty');
}
}
// Return the last penalty rule if the difference exceeds the overdueby value of the last rule.
$lastrule = end($penaltyrules);
if ($diff > $lastrule->get('overdueby')) {
return $lastrule->get('penalty');
}
// Return if no penalty rule is applicable.
return 0;
}
/**
* Find effective penalty rule which will be applied the course module.
*
* @param cm_info $cm The course module object.
* @return array
*/
private static function find_effective_penalty_rules(cm_info $cm): array {
// Course module context id.
$modulecontext = context_module::instance($cm->id);
$coursecontext = context_course::instance($cm->course);
$systemcontext = context_system::instance();
$contextids = [
$modulecontext->id,
$coursecontext->id,
$systemcontext->id,
];
// Get all penalty rules in one query.
$select = 'contextid IN (?, ?, ?)';
$penaltyrules = penalty_rule::get_records_select($select, $contextids, 'sortorder');
// Filter the penalty rules based on the context hierarchy.
foreach ($contextids as $contextid) {
$rules = array_filter($penaltyrules, function ($penaltyrule) use ($contextid): bool {
return (int) $penaltyrule->get('contextid') === (int) $contextid;
});
if (!empty($rules)) {
return $rules;
}
}
return [];
}
}