Skip to content

Commit

Permalink
CTP-4155 Update calculation for processed SORA data
Browse files Browse the repository at this point in the history
  • Loading branch information
aydevworks committed Dec 13, 2024
1 parent 3a9cc15 commit f792675
Show file tree
Hide file tree
Showing 17 changed files with 378 additions and 345 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/moodle-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:

services:
postgres:
image: postgres:13
image: postgres:14
env:
POSTGRES_USER: 'postgres'
POSTGRES_HOST_AUTH_METHOD: 'trust'
Expand Down
55 changes: 55 additions & 0 deletions classes/assessment/activity.php
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,28 @@ public function get_grade_items(): array {
return !(empty($gradeitems)) ? $gradeitems : [];
}

/**
* Delete all SORA overrides for the assessment.
*
* @return void
* @throws \coding_exception
* @throws \dml_exception
*/
public function delete_all_sora_overrides(): void {
global $CFG;
require_once($CFG->dirroot . '/group/lib.php');

// Find all the sora group overrides for the assessment.
$overrides = $this->get_assessment_sora_overrides();

// Delete all sora groups of that assessment from the course.
if (!empty($overrides)) {
foreach ($overrides as $override) {
groups_delete_group($override->groupid);
}
}
}

/**
* Set the module instance.
* @return void
Expand Down Expand Up @@ -221,4 +243,37 @@ protected function get_gradeable_enrolled_users_with_capability(string $capabili
return in_array($u->id, $gradeableids);
});
}

/**
* Remove user from previous SORA groups of the assessment.
* When a user is added to a new group, they should be removed from all other SORA groups of the assessment.
*
* @param int $userid User ID.
* @param int|null $excludedgroupid Group ID to exclude. This is the group that the user is being added to.
* @return void
*/
protected function remove_user_from_previous_sora_groups(int $userid, ?int $excludedgroupid = null): void {
// Get all the sora group overrides.
$overrides = $this->get_assessment_sora_overrides();

// No overrides to remove.
if (empty($overrides)) {
return;
}

foreach ($overrides as $override) {
// Skip the excluded group.
if ($excludedgroupid && $override->groupid == $excludedgroupid) {
continue;
}

// Remove the user from the previous SORA group.
groups_remove_member($override->groupid, $userid);

// Delete the group if it is empty.
if (empty(groups_get_members($override->groupid))) {
groups_delete_group($override->groupid);
}
}
}
}
25 changes: 9 additions & 16 deletions classes/assessment/assessment.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,17 @@ public function apply_extension(extension $extension): void {
if ($extension instanceof ec) {
$this->apply_ec_extension($extension);
} else if ($extension instanceof sora) {
// Skip SORA overrides if the assessment is not an exam.
if (!$this->is_exam()) {
return;
}
// Skip SORA overrides if the end date of the assessment is in the past.
if ($this->get_end_date() < time()) {
return;
}

// Remove user from all SORA groups in this assessment.
if ($extension->get_time_extension() == 0) {
$this->remove_user_from_previous_sora_groups($extension->get_userid());
return;
}

$this->apply_sora_extension($extension);
}
}
Expand Down Expand Up @@ -208,15 +210,6 @@ public function get_module_name(): string {
return '';
}

/**
* Check if the assessment is an exam. Override in child class if needed.
*
* @return bool
*/
public function is_exam(): bool {
return false;
}

/**
* Check if the assessment is valid for marks transfer.
*
Expand Down Expand Up @@ -264,13 +257,13 @@ public function is_valid_for_extension(): \stdClass {
}

/**
* Delete SORA override for a Moodle assessment.
* Delete all SORA override for a Moodle assessment.
* It is used to delete all SORA overrides for an assessment when the mapping is removed.
*
* @param array $groupids Default SORA overrides group ids in the course.
* @return void
* @throws \moodle_exception
*/
public function delete_sora_overrides(array $groupids): void {
public function delete_all_sora_overrides(): void {
// Default not supported. Override in child class if needed.
throw new \moodle_exception('error:soraextensionnotsupported', 'local_sitsgradepush');
}
Expand Down
92 changes: 34 additions & 58 deletions classes/assessment/assign.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,57 +67,6 @@ public function get_end_date(): ?int {
return $this->sourceinstance->duedate;
}

/**
* Check if this assignment is an exam.
*
* @return bool
*/
public function is_exam(): bool {
$start = $this->get_start_date();
$end = $this->get_end_date();

if ($start && $end) {
$duration = $end - $start;
return $duration > 0 && $duration <= HOURSECS * 5;
}

return false;
}

/**
* Delete SORA override for the assignment.
*
* @param array $groupids Default SORA overrides group ids in the course.
* @return void
* @throws \coding_exception
* @throws \dml_exception
*/
public function delete_sora_overrides(array $groupids): void {
global $CFG, $DB;
require_once($CFG->dirroot . '/mod/assign/locallib.php');

// Skip if group ids are empty.
if (empty($groupids)) {
return;
}

// Find all group overrides for the assignment having the default SORA overrides group ids.
[$insql, $params] = $DB->get_in_or_equal($groupids, SQL_PARAMS_NAMED);
$params['assignid'] = $this->sourceinstance->id;
$sql = "SELECT id FROM {assign_overrides} WHERE assignid = :assignid AND groupid $insql AND userid IS NULL";

$overrides = $DB->get_records_sql($sql, $params);

if (empty($overrides)) {
return;
}

$assign = new \assign($this->context, $this->get_course_module(), null);
foreach ($overrides as $override) {
$assign->delete_override($override->id);
}
}

/**
* Apply EC extension to the assessment.
*
Expand Down Expand Up @@ -150,24 +99,51 @@ protected function apply_sora_extension(sora $sora): void {
global $CFG;
require_once($CFG->dirroot . '/group/lib.php');

// Get time extension in seconds.
$timeextensionperhour = $sora->get_time_extension();

// Calculate the new due date.
// Find the difference between the start and end date in hours. Multiply by the time extension per hour.
$actualextension = (($this->get_end_date() - $this->get_start_date()) / HOURSECS) * $timeextensionperhour;
$newduedate = $this->get_end_date() + round($actualextension);
$newduedate = $this->get_end_date() + $sora->get_time_extension();

// Total extension in minutes.
$totalminutes = round($sora->get_time_extension() / MINSECS);

// Get the group id, create if it doesn't exist and add the user to the group.
$groupid = $sora->get_sora_group_id($this->get_course_id(), $sora->get_userid());
$groupid = $sora->get_sora_group_id(
$this->get_course_id(),
$this->get_coursemodule_id(),
$sora->get_userid(),
$totalminutes
);

if (!$groupid) {
throw new \moodle_exception('error:cannotgetsoragroupid', 'local_sitsgradepush');
}

// Remove the user from the previous SORA groups.
$this->remove_user_from_previous_sora_groups($sora->get_userid(), $groupid);
$this->overrides_due_date($newduedate, $sora->get_userid(), $groupid);
}

/**
* Get all SORA group overrides for the assignment.
*
* @return array
* @throws \dml_exception
*/
protected function get_assessment_sora_overrides(): array {
global $DB;
// Find all the group overrides for the assignment.
$sql = 'SELECT ao.* FROM {assign_overrides} ao
JOIN {groups} g ON ao.groupid = g.id
WHERE ao.assignid = :assignid AND ao.userid IS NULL AND g.name LIKE :name';

$params = [
'assignid' => $this->sourceinstance->id,
'name' => sora::SORA_GROUP_PREFIX . '%',
];

// Get all sora group overrides.
return $DB->get_records_sql($sql, $params);
}

/**
* Overrides the due date for the user or group.
*
Expand Down
82 changes: 33 additions & 49 deletions classes/assessment/quiz.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,48 +67,6 @@ public function get_end_date(): ?int {
return $this->get_source_instance()->timeclose;
}

/**
* Check if this quiz is an exam.
*
* @return bool
*/
public function is_exam(): bool {
$originaltimelimit = $this->get_source_instance()->timelimit;
return $originaltimelimit > 0 && $originaltimelimit <= HOURMINS * 5;
}

/**
* Delete SORA override for the quiz.
*
* @param array $groupids Default SORA overrides group ids in the course.
* @return void
* @throws \coding_exception
* @throws \dml_exception
*/
public function delete_sora_overrides(array $groupids): void {
global $CFG, $DB;
require_once($CFG->dirroot . '/mod/assign/locallib.php');

// Skip if group ids are empty.
if (empty($groupids)) {
return;
}

// Find all group overrides for the quiz having the default SORA overrides group ids.
[$insql, $params] = $DB->get_in_or_equal($groupids, SQL_PARAMS_NAMED);
$params['quizid'] = $this->sourceinstance->id;
$sql = "SELECT * FROM {quiz_overrides} WHERE quiz = :quizid AND groupid $insql AND userid IS NULL";

$overrides = $DB->get_records_sql($sql, $params);

if (empty($overrides)) {
return;
}

// Delete the overrides.
$this->get_override_manager()->delete_overrides($overrides);
}

/**
* Apply EC extension to the quiz.
*
Expand Down Expand Up @@ -136,15 +94,19 @@ protected function apply_ec_extension(ec $ec): void {
protected function apply_sora_extension(sora $sora): void {
global $DB;

// Get extra time from SORA.
$timeextension = $sora->get_time_extension();
// Calculate the time close for this sora override.
$newtimeclose = $this->get_end_date() + $sora->get_time_extension();

// Calculate the new time limit.
$originaltimelimit = $this->get_source_instance()->timelimit;
$newtimelimit = $originaltimelimit + (($originaltimelimit / HOURSECS) * $timeextension);
// Total extension in minutes.
$totalminutes = round($sora->get_time_extension() / MINSECS);

// Get the group id.
$groupid = $sora->get_sora_group_id($this->get_course_id(), $sora->get_userid());
$groupid = $sora->get_sora_group_id(
$this->get_course_id(),
$this->get_coursemodule_id(),
$sora->get_userid(),
$totalminutes
);

if (!$groupid) {
throw new \moodle_exception('error:cannotgetsoragroupid', 'local_sitsgradepush');
Expand All @@ -153,7 +115,7 @@ protected function apply_sora_extension(sora $sora): void {
$overridedata = [
'quiz' => $this->get_source_instance()->id,
'groupid' => $groupid,
'timelimit' => round($newtimelimit),
'timeclose' => $newtimeclose,
];

// Get the override record if it exists.
Expand All @@ -174,6 +136,28 @@ protected function apply_sora_extension(sora $sora): void {
$this->get_override_manager()->save_override($overridedata);
}

/**
* Get all SORA group overrides for the quiz.
*
* @return array
* @throws \dml_exception
*/
protected function get_assessment_sora_overrides() {
global $DB;
// Find all the group overrides for the quiz.
$sql = 'SELECT qo.* FROM {quiz_overrides} qo
JOIN {groups} g ON qo.groupid = g.id
WHERE qo.quiz = :quizid AND qo.userid IS NULL AND g.name LIKE :name';

$params = [
'quizid' => $this->sourceinstance->id,
'name' => sora::SORA_GROUP_PREFIX . '%',
];

// Get all the group overrides except the excluded group.
return $DB->get_records_sql($sql, $params);
}

/**
* Get the quiz override manager.
*
Expand Down
Loading

0 comments on commit f792675

Please sign in to comment.