Skip to content

Commit

Permalink
add duration-based grading method
Browse files Browse the repository at this point in the history
- Grade according to the duration of meeting attendance
- set the id with the name for non-registered users so we use it a unique identifier for the user.
- updating records of participants instate of adding new record in case if the non-registered user left the meeting and return

fixing some codes and try to fix phpunit test

add name condition

add a condition for checking the existence of the participant by name along with user id to avoid update existence record if the user id is null

this should pass the phpunit test

adding a condition to check the existence of a data in zoom_meeting_participants by name along with user id to prevent updating records of users with null id.

options for grading methods and display name

- Adding setting to choose the grading method.
- Adding setting to choose the display name.
- Removing the overlapped time when merging a participant record in duration.

get_participant_overlap_time

creating a function that properly calculate the overlap timing in the meeting reports.

Just make the code checker happier.

Update get_meeting_reports.php

forgot to include join_time field.

Creating a function to calculate users grades

- Creating a function to calculate users grades according to their duration in the meeting.
- Fixing the function get_participant_overlap_time().
- Move the code to calculate the grades outside the loop.
- return the original inserting data to the participants table.
- prevent inserting multiple data for exist record.
- not updating grades until the new grade is larger than the old one.

testing the new grading method

Notify teachers about grades

Send teachers a notification about grades in meeting according to duration.

test the notification

update tests

try preventResetByRollback() maybe messages test work!

try to make messages work

changing teacher role to editingteacher

change graders array key

fix message index

fix misspelling

Add and fix comments

remove wrong using class and fix some comments

check the existence of user after integer check

Try not to be spamy

As the task get_meeting_reports run, don't send notifications unless there is new records in meeting participants table

Help teacher to fine ungraded users

Narrowing the options for teachers needing to grade non-recognized students in participant meeting report.

Adding a function to get a list of users clicked (join meeting)
using this function and excluding already recognized students
displaying a list of the rest student in the notification message to teachers

try to solve null readers

try to skip error: Call to a member function get_events_select() on null on PHPUnit test.

phpcs: small cleanups

New grading method is in module level

- Add new field to mod_form to specify the grading method instead of specify it on the admin level.

fix typo and version

Change gradefor field to grading_method

namespace: convert to use statements

use messages

Co-authored-by: Jonathan Champ <[email protected]>
  • Loading branch information
fmido88 and jrchamp committed Dec 14, 2023
1 parent d4559a9 commit c481e23
Show file tree
Hide file tree
Showing 13 changed files with 949 additions and 34 deletions.
2 changes: 1 addition & 1 deletion backup/moodle2/backup_zoom_stepslib.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class backup_activity_structure_step extends \backup_activity_structure_step {
protected function define_structure() {
// Define the root element describing the zoom instance.
$zoom = new backup_nested_element('zoom', ['id'], [
'intro', 'introformat', 'grade', 'meeting_id', 'join_url', 'created_at', 'host_id', 'name',
'intro', 'introformat', 'grade', 'grading_method', 'meeting_id', 'join_url', 'created_at', 'host_id', 'name',
'start_time', 'timemodified', 'recurring', 'recurrence_type', 'repeat_interval', 'weekly_days', 'monthly_day',
'monthly_week', 'monthly_week_day', 'monthly_repeat_option', 'end_times', 'end_date_time', 'end_date_option',
'webinar', 'duration', 'timezone', 'password', 'option_jbh', 'option_start_type', 'option_host_video',
Expand Down
2 changes: 1 addition & 1 deletion backup/moodle2/restore_zoom_stepslib.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ protected function define_structure() {
protected function process_zoom($data) {
global $DB;

$data = (object)$data;
$data = (object) $data;

// Update start_time before attempting to create a new meeting.
$data->start_time = $this->apply_date_offset($data->start_time);
Expand Down
444 changes: 432 additions & 12 deletions classes/task/get_meeting_reports.php

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion db/install.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="mod/zoom/db" VERSION="20231116" COMMENT="Zoom module"
<XMLDB PATH="mod/zoom/db" VERSION="20240105" COMMENT="Zoom module"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
Expand All @@ -11,6 +11,7 @@
<FIELD NAME="intro" TYPE="text" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="introformat" TYPE="int" LENGTH="4" NOTNULL="false" SEQUENCE="false" COMMENT="Format of description field"/>
<FIELD NAME="grade" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="Maximum grade (points possible) for this activity. Negative value indicates a scale being used."/>
<FIELD NAME="grading_method" TYPE="char" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="Add the grading method by entering the meeting or according the attendance duration."/>
<FIELD NAME="meeting_id" TYPE="int" LENGTH="15" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="join_url" TYPE="text" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="created_at" TYPE="char" LENGTH="20" NOTNULL="false" SEQUENCE="false" COMMENT="ISO datetime format"/>
Expand Down
29 changes: 29 additions & 0 deletions db/messages.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?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/>.

/**
* Defines message providers for mod_zoom.
*
* @package mod_zoom
* @copyright 2023 Mo Farouk <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

defined('MOODLE_INTERNAL') || die();

$messageproviders = [
'teacher_notification' => [],
];
14 changes: 14 additions & 0 deletions db/upgrade.php
Original file line number Diff line number Diff line change
Expand Up @@ -933,5 +933,19 @@ function xmldb_zoom_upgrade($oldversion) {
upgrade_mod_savepoint(true, 2023111600, 'zoom');
}

if ($oldversion < 2024010500) {
// Define field grading_method to be added to zoom.
$table = new xmldb_table('zoom');
$field = new xmldb_field('grading_method', XMLDB_TYPE_CHAR, '10', null, null, null, null, 'grade');

// Conditionally launch add field grading_method.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}

// Zoom savepoint reached.
upgrade_mod_savepoint(true, 2024010500, 'zoom');
}

return true;
}
42 changes: 42 additions & 0 deletions lang/en/zoom.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@
$string['displayleadtime'] = 'Display lead time';
$string['displayleadtime_desc'] = 'If enabled, the leadtime will be displayed to the users. This way, users are informed that / when they can join the meeting before the scheduled start time. This might keep users from constantly reloading the page until they can join.';
$string['displayleadtime_nohideif'] = 'Please note: This setting is only processed if the \'{$a}\' setting is set to a value greater than zero.';
$string['displayfullname'] = 'Full name';
$string['displayfirstname'] = 'First name only';
$string['displayidfullname'] = '(user id) followed by fullname';
$string['displayid'] = '(user id) only';
$string['displaypassword'] = 'Display passcode';
$string['displaypassword_help'] = 'If enabled the meeting passcode will always be displayed to non-hosts.';
$string['downloadical'] = 'Download iCal';
Expand Down Expand Up @@ -138,6 +142,40 @@
$string['getmeetingrecordings'] = 'Get meeting recordings from Zoom';
$string['globalsettings'] = 'Global settings';
$string['globalsettings_desc'] = 'These settings apply to the Zoom plugin as a whole.';
$string['grading_needgrade'] = "The following users need to be graded manually as they could not be identified:\n";
$string['grading_notenrolled'] = "The following users joined the meeting but were not recognized as enroled users:\n";
$string['grading_notfound'] = "List of users who clicked to join the meeting, but were not recognized in the participant report:\n";
$string['gradinglink'] = 'Review or update grades';
$string['gradingmessagesubject'] = 'User grades for Zoom meeting: {$a->name}';
$string['gradingmessagebody'] = 'For Zoom Meeting session: {$a->zoomurl};
<br>
Number of users that have been automatically graded according to their duration in the meeting: {$a->graded}.
<br>
Number of users that were already graded: {$a->alreadygraded}.
<br>
{$a->needgrade}<br>
Review or update users grades here: {$a->gradeurl}
<br>
{$a->notfound}
<br>
{$a->notenrolled}';
$string['gradingsmallmeassage'] = 'User grades quick report for {$a->name}:
<br>
Need manual grading: {$a->number}
<br>
Graded users: {$a->graded + $a->alreadygraded}';
$string['gradingmethod_heading'] = 'Options for grading method';
$string['gradingmethod_heading_help'] = 'Decide which method to use when grading Zoom participation.';
$string['gradingmethod'] = 'Grading method';
$string['gradingmethod_help'] = 'Choose the method to use when grading student participation.<br>
Upon entry: the student receives full marks (max grade) when they click to join the meeting in Moodle.<br>
Attendance duration: the student receives a score based on the percentage of their meeting attendance compared to the total meeting duration.<br>
Notes regarding Attendance duration method:<br>
- This method requires the display name to contain id or fullname.<br>
- It is recommended to set the setting \'zoom | defaultjoinbeforehost\' to (No) so the meeting duration is accurate.<br>
- Some students who are already signed in to the Zoom client with details not matching those in Moodle must be graded manually after reviewing the meeting report.';
$string['gradingentry'] = 'Upon entry';
$string['gradingperiod'] = 'Attendance Duration';
$string['host'] = 'Host';
$string['hostintro'] = '<a target="_blank" href="https://support.zoom.us/hc/en-us/articles/208220166">Alternative Hosts</a> can start Zoom meetings and manage the Waiting Room.';
$string['indicator:cognitivedepth'] = 'Zoom cognitive';
Expand Down Expand Up @@ -207,6 +245,7 @@
$string['meetingcapacitywarningcontactalthost'] = 'Please ask the host to turn to the Zoom account owner to obtain a larger Zoom license if all of these course participants need to join the meeting.';
$string['meetingparticipantsdeleted'] = 'Meeting participant user data deleted.';
$string['meetingrecordingviewsdeleted'] = 'Meeting recording user view data deleted.';
$string['messageprovider:teacher_notification'] = 'Notify teachers about user grades (according to duration) in a Zoom session';
$string['modulename'] = 'Zoom meeting';
$string['modulenameplural'] = 'Zoom Meetings';
$string['modulename_help'] = 'Zoom is a video and web conferencing platform that gives authorized users the ability to host online meetings.';
Expand All @@ -215,6 +254,7 @@
$string['nextoccurrence'] = 'Next occurrence';
$string['newmeetings'] = 'New Meetings';
$string['nomeetinginstances'] = 'No sessions found for this meeting.';
$string['nonrecognizedusergrade'] = '(Name: {$a->userid}, grade: {$a->grade})';
$string['nooccurrenceleft'] = 'The last occurrence is already over';
$string['noparticipants'] = 'No participants found for this session at this time.';
$string['norecordings'] = 'No recordings found for this meeting at this time.';
Expand Down Expand Up @@ -371,6 +411,8 @@
$string['unavailablenotstartedyet'] = 'The meeting has not started yet.';
$string['updatemeetings'] = 'Update meeting settings from Zoom';
$string['updatetrackingfields'] = 'Update tracking field settings from Zoom';
$string['unamedisplay'] = 'User display name';
$string['unamedisplay_help'] = 'How the name of a user should be displayed in meetings (only works for users who are not logged in to the Zoom client).';
$string['usepersonalmeeting'] = 'Use personal meeting ID {$a}';
$string['waitingroom'] = 'Waiting room';
$string['waitingroomenable'] = 'Enable waiting room';
Expand Down
2 changes: 1 addition & 1 deletion lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,7 @@ function zoom_grade_item_update(stdClass $zoom, $grades = null) {
* Delete grade item for given zoom instance
*
* @param stdClass $zoom instance object
* @return grade_item
* @return int
*/
function zoom_grade_item_delete($zoom) {
global $CFG;
Expand Down
66 changes: 49 additions & 17 deletions locallib.php
Original file line number Diff line number Diff line change
Expand Up @@ -970,7 +970,28 @@ function zoom_load_meeting($id, $context, $usestarturl = true) {
$url = $registrantjoinurl;
}

$returns['nexturl'] = new moodle_url($url, ['uname' => fullname($USER)]);
$unamesetting = get_config('zoom', 'unamedisplay');
switch ($unamesetting) {
case 'fullname':
default:
$unamedisplay = fullname($USER);
break;

case 'firstname':
$unamedisplay = $USER->firstname;
break;

case 'idfullname':
$unamedisplay = '(' . $USER->id . ') ' . fullname($USER);
break;

case 'id':
$unamedisplay = '(' . $USER->id . ')';
break;
}

// Try to send the user email (not guaranteed).
$returns['nexturl'] = new moodle_url($url, ['uname' => $unamedisplay, 'uemail' => $USER->email]);
}

// If the user is pre-registering, skip grading/completion.
Expand All @@ -993,24 +1014,35 @@ function zoom_load_meeting($id, $context, $usestarturl = true) {
$completion = new completion_info($course);
$completion->set_module_viewed($cm);

// Check whether user has a grade. If not, then assign full credit to them.
$gradelist = grade_get_grades($course->id, 'mod', 'zoom', $cm->instance, $USER->id);

// Assign full credits for user who has no grade yet, if this meeting is gradable (i.e. the grade type is not "None").
if (!empty($gradelist->items) && empty($gradelist->items[0]->grades[$USER->id]->grade)) {
$grademax = $gradelist->items[0]->grademax;
$grades = [
'rawgrade' => $grademax,
'userid' => $USER->id,
'usermodified' => $USER->id,
'dategraded' => '',
'feedbackformat' => '',
'feedback' => '',
];

zoom_grade_item_update($zoom, $grades);
// Check the grading method settings.
if (!empty($zoom->grading_method)) {
$gradingmethod = $zoom->grading_method;
} else if ($defaultgrading = get_config('gradingmethod', 'zoom')) {
$gradingmethod = $defaultgrading;
} else {
$gradingmethod = 'entry';
}

if ($gradingmethod === 'entry') {
// Check whether user has a grade. If not, then assign full credit to them.
$gradelist = grade_get_grades($course->id, 'mod', 'zoom', $cm->instance, $USER->id);

// Assign full credits for user who has no grade yet, if this meeting is gradable (i.e. the grade type is not "None").
if (!empty($gradelist->items) && empty($gradelist->items[0]->grades[$USER->id]->grade)) {
$grademax = $gradelist->items[0]->grademax;
$grades = [
'rawgrade' => $grademax,
'userid' => $USER->id,
'usermodified' => $USER->id,
'dategraded' => '',
'feedbackformat' => '',
'feedback' => '',
];

zoom_grade_item_update($zoom, $grades);
}
} // Otherwise, the get_meetings_report task calculates the grades according to duration.

// Upgrade host upon joining meeting, if host is not Licensed.
if ($userishost) {
$config = get_config('zoom');
Expand Down
20 changes: 20 additions & 0 deletions mod_form.php
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,26 @@ public function definition() {
$this->add_action_buttons();
}

/**
* Add standard_grading_coursemodule_elements with grading for field.
* @return void
*/
public function standard_grading_coursemodule_elements() {
parent::standard_grading_coursemodule_elements();
$mform = $this->_form;
$itemnumber = 0;
$component = "mod_{$this->_modname}";
$gradefieldname = \core_grades\component_gradeitems::get_field_name_for_itemnumber($component, $itemnumber, 'grade');
$options = [
'entry' => get_string('gradingentry', 'mod_zoom'), // All credit upon entry.
'period' => get_string('gradingperiod', 'mod_zoom'), // Credit according to attend duration.
];
$mform->addElement('select', 'grading_method', get_string('gradingmethod', 'mod_zoom'), $options);
$mform->setDefault('grading_method', get_config('zoom', 'gradingmethod'));
$mform->addHelpButton('grading_method', 'gradingmethod', 'zoom');
$mform->hideIf('grading_method', "{$gradefieldname}[modgrade_type]", 'eq', 'none');
}

/**
* Fill in the current page data for this course.
*/
Expand Down
36 changes: 36 additions & 0 deletions settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,21 @@
);
$settings->add($viewrecordings);

// Adding options for the display name using uname parameter in zoom join_url.
$options = [
'fullname' => get_string('displayfullname', 'mod_zoom'),
'firstname' => get_string('displayfirstname', 'mod_zoom'),
'idfullname' => get_string('displayidfullname', 'mod_zoom'),
'id' => get_string('displayid', 'mod_zoom'),
];
$settings->add(new admin_setting_configselect(
'zoom/unamedisplay',
get_string('unamedisplay', 'mod_zoom'),
get_string('unamedisplay_help', 'mod_zoom'),
'fullname',
$options
));

// Supplementary features settings.
$settings->add(new admin_setting_heading(
'zoom/supplementaryfeaturessettings',
Expand Down Expand Up @@ -615,4 +630,25 @@
$settings->hide_if('zoom/invitation_invite', 'zoom/invitationremoveinvite', 'eq', 0);
$settings->hide_if('zoom/invitation_icallink', 'zoom/invitationremoveicallink', 'eq', 0);
}

// Adding options for grading methods.
$settings->add(new admin_setting_heading(
'zoom/gradingmethod',
get_string('gradingmethod_heading', 'mod_zoom'),
get_string('gradingmethod_heading_help', 'mod_zoom')
));

// Grading method upon entry: the user gets the full score when clicking to join the session through Moodle.
// Grading method upon period: the user is graded based on how long they attended the actual session.
$options = [
'entry' => get_string('gradingentry', 'mod_zoom'),
'period' => get_string('gradingperiod', 'mod_zoom'),
];
$settings->add(new admin_setting_configselect(
'zoom/gradingmethod',
get_string('gradingmethod', 'mod_zoom'),
get_string('gradingmethod_help', 'mod_zoom'),
'entry',
$options
));
}
Loading

0 comments on commit c481e23

Please sign in to comment.