Dan Marsden
9 years ago
14 changed files with 781 additions and 470 deletions
@ -0,0 +1,268 @@ |
|||||
|
<?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/>. |
||||
|
|
||||
|
/** |
||||
|
* Class that computes summary of users points |
||||
|
* |
||||
|
* @package mod_attendance |
||||
|
* @copyright 2016 Antonio Carlos Mariani http://antonio.c.mariani@gmail.com |
||||
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later |
||||
|
*/ |
||||
|
|
||||
|
require_once($CFG->dirroot . '/mod/attendance/locallib.php'); |
||||
|
|
||||
|
class mod_attendance_summary { |
||||
|
|
||||
|
/** @var int attendance instance identifier */ |
||||
|
private $attendanceid; |
||||
|
|
||||
|
/** @var stdclass course course data*/ |
||||
|
private $course; |
||||
|
|
||||
|
/** @var int groupmode*/ |
||||
|
private $groupmode; |
||||
|
|
||||
|
/** @var array userspoints (userid, numtakensessions, points, maxpoints) */ |
||||
|
private $userspoints; |
||||
|
|
||||
|
/** @var array pointsbygroup (groupid, numsessions, maxpoints) */ |
||||
|
private $maxpointsbygroupsessions; |
||||
|
|
||||
|
/** |
||||
|
* Initializes the class |
||||
|
* |
||||
|
* @param int attendance instance identifier |
||||
|
* @param array userids user instances identifier |
||||
|
* @param int $startdate Attendance sessions startdate |
||||
|
* @param int $enddate Attendance sessions enddate |
||||
|
*/ |
||||
|
public function __construct($attendanceid, $userids=array(), $startdate = '', $enddate = '') { |
||||
|
$this->attendanceid = $attendanceid; |
||||
|
|
||||
|
$this->compute_users_points($userids, $startdate, $enddate); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Returns true if the user has some session with points |
||||
|
* |
||||
|
* @param int userid User instance id |
||||
|
* |
||||
|
* @return boolean |
||||
|
*/ |
||||
|
public function has_taken_sessions($userid) { |
||||
|
return isset($this->userspoints[$userid]); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Returns true if the corresponding attendance instance is currently configure to work with grades (points) |
||||
|
* |
||||
|
* @return boolean |
||||
|
*/ |
||||
|
public function with_groups() { |
||||
|
return $this->groupmode > 0; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Returns the groupmode of the corresponding attendance instance |
||||
|
* |
||||
|
* @return int |
||||
|
*/ |
||||
|
public function get_groupmode() { |
||||
|
return $this->groupmode; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Returns the percentages of each user related to the taken sessions |
||||
|
* |
||||
|
* @return array |
||||
|
*/ |
||||
|
public function get_user_taken_sessions_percentages() { |
||||
|
$percentages = array(); |
||||
|
|
||||
|
foreach ($this->userspoints as $userid => $userpoints) { |
||||
|
$percentages[$userid] = attendance_calc_fraction($userpoints->points, $userpoints->maxpoints); |
||||
|
} |
||||
|
|
||||
|
return $percentages; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Returns a summary of the points assigned to the user related to the taken sessions |
||||
|
* |
||||
|
* @param int userid User instance id |
||||
|
* |
||||
|
* @return array |
||||
|
*/ |
||||
|
public function get_taken_sessions_summary_for($userid) { |
||||
|
$usersummary = new stdClass(); |
||||
|
if ($this->has_taken_sessions($userid)) { |
||||
|
$usersummary->numtakensessions = $this->userspoints[$userid]->numtakensessions; |
||||
|
$usersummary->takensessionspoints = $this->userspoints[$userid]->points; |
||||
|
$usersummary->takensessionsmaxpoints = $this->userspoints[$userid]->maxpoints; |
||||
|
} else { |
||||
|
$usersummary->numtakensessions = 0; |
||||
|
$usersummary->takensessionspoints = 0; |
||||
|
$usersummary->takensessionsmaxpoints = 0; |
||||
|
} |
||||
|
$usersummary->takensessionspercentage = attendance_calc_fraction($usersummary->takensessionspoints, |
||||
|
$usersummary->takensessionsmaxpoints); |
||||
|
|
||||
|
return $usersummary; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Returns a summary of the points assigned to the user, both related to taken sessions and related to all sessions |
||||
|
* |
||||
|
* @param int userid User instance id |
||||
|
* |
||||
|
* @return array |
||||
|
*/ |
||||
|
public function get_all_sessions_summary_for($userid) { |
||||
|
$usersummary = $this->get_taken_sessions_summary_for($userid); |
||||
|
|
||||
|
if (!isset($this->maxpointsbygroupsessions)) { |
||||
|
$this->compute_maxpoints_by_group_session(); |
||||
|
} |
||||
|
|
||||
|
$usersummary->numallsessions = $this->maxpointsbygroupsessions[0]->numsessions; |
||||
|
$usersummary->allsessionsmaxpoints = $this->maxpointsbygroupsessions[0]->maxpoints; |
||||
|
|
||||
|
if ($this->with_groups()) { |
||||
|
$groupids = array_keys(groups_get_all_groups($this->course->id, $userid)); |
||||
|
foreach ($groupids as $gid) { |
||||
|
if (isset($this->maxpointsbygroupsessions[$gid])) { |
||||
|
$usersummary->numallsessions += $this->maxpointsbygroupsessions[$gid]->numsessions; |
||||
|
$usersummary->allsessionsmaxpoints += $this->maxpointsbygroupsessions[$gid]->maxpoints; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
$usersummary->allsessionspercentage = attendance_calc_fraction($usersummary->takensessionspoints, |
||||
|
$usersummary->allsessionsmaxpoints); |
||||
|
|
||||
|
$deltapoints = $usersummary->allsessionsmaxpoints - $usersummary->takensessionsmaxpoints; |
||||
|
$usersummary->maxpossiblepoints = $usersummary->takensessionspoints + $deltapoints; |
||||
|
$usersummary->maxpossiblepercentage = attendance_calc_fraction($usersummary->maxpossiblepoints, |
||||
|
$usersummary->allsessionsmaxpoints); |
||||
|
|
||||
|
return $usersummary; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Computes the summary of points for the users that have some taken session |
||||
|
* |
||||
|
* @param array userids user instances identifier |
||||
|
* @param int $startdate Attendance sessions startdate |
||||
|
* @param int $enddate Attendance sessions enddate |
||||
|
* @return (userid, numtakensessions, points, maxpoints) |
||||
|
*/ |
||||
|
private function compute_users_points($userids=array(), $startdate = '', $enddate = '') { |
||||
|
global $DB; |
||||
|
|
||||
|
list($this->course, $cm) = get_course_and_cm_from_instance($this->attendanceid, 'attendance'); |
||||
|
$this->groupmode = $cm->effectivegroupmode; |
||||
|
|
||||
|
$params = array( |
||||
|
'attid' => $this->attendanceid, |
||||
|
'attid2' => $this->attendanceid, |
||||
|
'cstartdate' => $this->course->startdate, |
||||
|
); |
||||
|
|
||||
|
$where = ''; |
||||
|
if (!empty($userids)) { |
||||
|
list($insql, $inparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED); |
||||
|
$where .= ' AND atl.studentid ' . $insql; |
||||
|
$params = array_merge($params, $inparams); |
||||
|
} |
||||
|
if (!empty($startdate)) { |
||||
|
$where .= ' AND ats.sessdate >= :startdate'; |
||||
|
$params['startdate'] = $startdate; |
||||
|
} |
||||
|
if (!empty($enddate)) { |
||||
|
$where .= ' AND ats.sessdate < :enddate '; |
||||
|
$params['enddate'] = $enddate; |
||||
|
} |
||||
|
|
||||
|
$joingroup = ''; |
||||
|
if ($this->with_groups()) { |
||||
|
$joingroup = 'LEFT JOIN {groups_members} gm ON (gm.userid = atl.studentid AND gm.groupid = ats.groupid)'; |
||||
|
$where .= ' AND (ats.groupid = 0 or gm.id is NOT NULL)'; |
||||
|
} else { |
||||
|
$where .= ' AND ats.groupid = 0'; |
||||
|
} |
||||
|
|
||||
|
$sql = " SELECT atl.studentid AS userid, COUNT(DISTINCT ats.id) AS numtakensessions, |
||||
|
SUM(stg.grade) AS points, SUM(stm.maxgrade) AS maxpoints |
||||
|
FROM {attendance_sessions} ats |
||||
|
JOIN {attendance_log} atl ON (atl.sessionid = ats.id) |
||||
|
JOIN {attendance_statuses} stg ON (stg.id = atl.statusid AND stg.deleted = 0 AND stg.visible = 1) |
||||
|
JOIN (SELECT setnumber, MAX(grade) AS maxgrade |
||||
|
FROM {attendance_statuses} |
||||
|
WHERE attendanceid = :attid2 |
||||
|
AND deleted = 0 |
||||
|
AND visible = 1 |
||||
|
GROUP BY setnumber) stm |
||||
|
ON (stm.setnumber = ats.statusset) |
||||
|
{$joingroup} |
||||
|
WHERE ats.attendanceid = :attid |
||||
|
AND ats.sessdate >= :cstartdate |
||||
|
AND ats.lasttakenby != 0 |
||||
|
{$where} |
||||
|
GROUP BY atl.studentid"; |
||||
|
$this->userspoints = $DB->get_records_sql($sql, $params); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Computes and store the maximum points possible for each group session |
||||
|
* |
||||
|
* @return null |
||||
|
*/ |
||||
|
private function compute_maxpoints_by_group_session() { |
||||
|
global $DB; |
||||
|
|
||||
|
$params = array( |
||||
|
'attid' => $this->attendanceid, |
||||
|
'attid2' => $this->attendanceid, |
||||
|
'cstartdate' => $this->course->startdate, |
||||
|
); |
||||
|
|
||||
|
$where = ''; |
||||
|
if (!$this->with_groups()) { |
||||
|
$where = 'AND sess.groupid = 0'; |
||||
|
} |
||||
|
|
||||
|
$sql = "SELECT sess.groupid, COUNT(*) AS numsessions, SUM(stamax.maxgrade) AS maxpoints |
||||
|
FROM {attendance_sessions} sess |
||||
|
JOIN (SELECT setnumber, MAX(grade) AS maxgrade |
||||
|
FROM {attendance_statuses} |
||||
|
WHERE attendanceid = :attid2 |
||||
|
AND deleted = 0 |
||||
|
AND visible = 1 |
||||
|
GROUP BY setnumber) stamax |
||||
|
ON (stamax.setnumber = sess.statusset) |
||||
|
WHERE sess.attendanceid = :attid |
||||
|
AND sess.sessdate >= :cstartdate |
||||
|
{$where} |
||||
|
GROUP BY sess.groupid"; |
||||
|
$this->maxpointsbygroupsessions = $DB->get_records_sql($sql, $params); |
||||
|
|
||||
|
if (!isset($this->maxpointsbygroupsessions[0])) { |
||||
|
$gpoints = new stdClass(); |
||||
|
$gpoints->numsessions = 0; |
||||
|
$gpoints->maxpoints = 0; |
||||
|
$this->maxpointsbygroupsessions[0] = $gpoints; |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,240 @@ |
|||||
|
@javascript @mod @uon @mod_attendance |
||||
|
Feature: Visiting reports |
||||
|
As a teacher I visit the reports |
||||
|
|
||||
|
Background: |
||||
|
Given the following "courses" exist: |
||||
|
| fullname | shortname | summary | category | |
||||
|
| Course 1 | C101 | Prove the attendance activity works | 0 | |
||||
|
And the following "users" exist: |
||||
|
| username | firstname | lastname | email | idnumber | department | institution | |
||||
|
| student1 | Student | 1 | student1@asd.com | 1234 | computer science | University of Nottingham | |
||||
|
| teacher1 | Teacher | 1 | teacher1@asd.com | 5678 | computer science | University of Nottingham | |
||||
|
And the following "course enrolments" exist: |
||||
|
| user | course | role | |
||||
|
| student1 | C101 | student | |
||||
|
| teacher1 | C101 | editingteacher | |
||||
|
|
||||
|
And I log in as "teacher1" |
||||
|
And I follow "Course 1" |
||||
|
And I turn editing mode on |
||||
|
Then I add a "Attendance" to section "1" |
||||
|
And I press "Save and display" |
||||
|
And I follow "Attendance" |
||||
|
And I follow "Add session" |
||||
|
And I set the following fields to these values: |
||||
|
| id_sestime_starthour | 01 | |
||||
|
| id_sestime_endhour | 02 | |
||||
|
And I click on "id_submitbutton" "button" |
||||
|
|
||||
|
And I log out |
||||
|
|
||||
|
Scenario: Teacher takes attendance |
||||
|
When I log in as "teacher1" |
||||
|
And I follow "Course 1" |
||||
|
And I follow "Attendance" |
||||
|
And I follow "Edit settings" |
||||
|
Then I set the following fields to these values: |
||||
|
| id_grade_modgrade_type | Point | |
||||
|
| id_grade_modgrade_point | 50 | |
||||
|
And I press "Save and display" |
||||
|
|
||||
|
When I follow "Report" |
||||
|
Then "0 / 0" "text" should exist in the "Student 1" "table_row" |
||||
|
And "0.0%" "text" should exist in the "Student 1" "table_row" |
||||
|
|
||||
|
When I follow "Grades" in the user menu |
||||
|
And I follow "Course 1" |
||||
|
And "-" "text" should exist in the "Student 1" "table_row" |
||||
|
|
||||
|
When I follow "Attendance" |
||||
|
Then I click on "Take attendance" "link" in the "01:00 - 02:00" "table_row" |
||||
|
# Late |
||||
|
And I click on "td.c3 input" "css_element" in the "Student 1" "table_row" |
||||
|
And I press "Save attendance" |
||||
|
|
||||
|
When I follow "Report" |
||||
|
Then "1 / 2" "text" should exist in the "Student 1" "table_row" |
||||
|
And "50.0%" "text" should exist in the "Student 1" "table_row" |
||||
|
|
||||
|
When I follow "Grades" in the user menu |
||||
|
And I follow "Course 1" |
||||
|
And "25.00" "text" should exist in the "Student 1" "table_row" |
||||
|
|
||||
|
And I log out |
||||
|
|
||||
|
Scenario: Teacher changes the maximum points in the attendance settings |
||||
|
When I log in as "teacher1" |
||||
|
And I follow "Course 1" |
||||
|
And I follow "Attendance" |
||||
|
And I follow "Edit settings" |
||||
|
Then I set the following fields to these values: |
||||
|
| id_grade_modgrade_type | Point | |
||||
|
| id_grade_modgrade_point | 50 | |
||||
|
And I press "Save and display" |
||||
|
|
||||
|
When I follow "Attendance" |
||||
|
Then I click on "Take attendance" "link" in the "01:00 - 02:00" "table_row" |
||||
|
# Excused |
||||
|
And I click on "td.c3 input" "css_element" in the "Student 1" "table_row" |
||||
|
And I press "Save attendance" |
||||
|
|
||||
|
When I follow "Attendance" |
||||
|
And I follow "Edit settings" |
||||
|
Then I set the following fields to these values: |
||||
|
| id_grade_modgrade_type | Point | |
||||
|
| id_grade_modgrade_point | 70 | |
||||
|
And I press "Save and display" |
||||
|
|
||||
|
When I follow "Report" |
||||
|
Then "1 / 2" "text" should exist in the "Student 1" "table_row" |
||||
|
And "50.0%" "text" should exist in the "Student 1" "table_row" |
||||
|
|
||||
|
When I follow "Grades" in the user menu |
||||
|
And I follow "Course 1" |
||||
|
Then "35.00" "text" should exist in the "Student 1" "table_row" |
||||
|
|
||||
|
And I log out |
||||
|
|
||||
|
Scenario: Teacher take attendance of group session |
||||
|
Given the following "groups" exist: |
||||
|
| course | name | idnumber | |
||||
|
| C101 | Group1 | Group1 | |
||||
|
And the following "group members" exist: |
||||
|
| group | user | |
||||
|
| Group1 | student1 | |
||||
|
|
||||
|
When I log in as "teacher1" |
||||
|
And I follow "Course 1" |
||||
|
And I follow "Attendance" |
||||
|
And I follow "Edit settings" |
||||
|
And I set the following fields to these values: |
||||
|
| id_grade_modgrade_type | Point | |
||||
|
| id_grade_modgrade_point | 50 | |
||||
|
| id_groupmode | Visible groups | |
||||
|
And I press "Save and display" |
||||
|
|
||||
|
When I follow "Attendance" |
||||
|
Then I click on "Take attendance" "link" in the "01:00 - 02:00" "table_row" |
||||
|
# Excused |
||||
|
And I click on "td.c3 input" "css_element" in the "Student 1" "table_row" |
||||
|
And I press "Save attendance" |
||||
|
|
||||
|
When I follow "Add session" |
||||
|
And I set the following fields to these values: |
||||
|
| id_sestime_starthour | 03 | |
||||
|
| id_sestime_endhour | 04 | |
||||
|
| id_sessiontype_1 | 1 | |
||||
|
| id_groups | Group1 | |
||||
|
And I click on "id_submitbutton" "button" |
||||
|
Then I should see "03:00 - 04:00" |
||||
|
And "Group: Group1" "text" should exist in the "03:00 - 04:00" "table_row" |
||||
|
|
||||
|
When I click on "Take attendance" "link" in the "03:00 - 04:00" "table_row" |
||||
|
# Present |
||||
|
And I click on "td.c2 input" "css_element" in the "Student 1" "table_row" |
||||
|
And I press "Save attendance" |
||||
|
|
||||
|
When I follow "Report" |
||||
|
Then "Student 1" row "Points" column of "generaltable" table should contain "3 / 4" |
||||
|
And "Student 1" row "Percentage" column of "generaltable" table should contain "75.0%" |
||||
|
|
||||
|
When I follow "Grades" in the user menu |
||||
|
And I follow "Course 1" |
||||
|
Then "37.50" "text" should exist in the "Student 1" "table_row" |
||||
|
|
||||
|
And I log out |
||||
|
|
||||
|
Scenario: Teacher visit summary report |
||||
|
When I log in as "teacher1" |
||||
|
And I follow "Course 1" |
||||
|
And I follow "Attendance" |
||||
|
And I follow "Edit settings" |
||||
|
And I set the following fields to these values: |
||||
|
| id_grade_modgrade_type | Point | |
||||
|
| id_grade_modgrade_point | 50 | |
||||
|
And I press "Save and display" |
||||
|
|
||||
|
When I click on "Take attendance" "link" in the "01:00 - 02:00" "table_row" |
||||
|
# Late |
||||
|
And I click on "td.c3 input" "css_element" in the "Student 1" "table_row" |
||||
|
And I press "Save attendance" |
||||
|
|
||||
|
When I follow "Add session" |
||||
|
And I set the following fields to these values: |
||||
|
| id_sestime_starthour | 03 | |
||||
|
| id_sestime_endhour | 04 | |
||||
|
And I click on "id_submitbutton" "button" |
||||
|
Then I should see "03:00 - 04:00" |
||||
|
|
||||
|
When I click on "Take attendance" "link" in the "03:00 - 04:00" "table_row" |
||||
|
# Present |
||||
|
And I click on "td.c2 input" "css_element" in the "Student 1" "table_row" |
||||
|
And I press "Save attendance" |
||||
|
|
||||
|
When I follow "Add session" |
||||
|
And I set the following fields to these values: |
||||
|
| id_sestime_starthour | 05 | |
||||
|
| id_sestime_endhour | 06 | |
||||
|
And I click on "id_submitbutton" "button" |
||||
|
Then I should see "05:00 - 06:00" |
||||
|
|
||||
|
When I follow "Report" |
||||
|
And I click on "Summary" "link" in the "All" "table_row" |
||||
|
Then "Student 1" row "Total number of sessions" column of "generaltable" table should contain "3" |
||||
|
And "Student 1" row "Points over all sessions" column of "generaltable" table should contain "3 / 6" |
||||
|
And "Student 1" row "Percentage over all sessions" column of "generaltable" table should contain "50.0%" |
||||
|
And "Student 1" row "Maximum possible points" column of "generaltable" table should contain "5 / 6" |
||||
|
And "Student 1" row "Maximum possible percentage" column of "generaltable" table should contain "83.3%" |
||||
|
|
||||
|
And I log out |
||||
|
|
||||
|
Scenario: Student visit user report |
||||
|
When I log in as "teacher1" |
||||
|
And I follow "Course 1" |
||||
|
And I follow "Attendance" |
||||
|
And I follow "Edit settings" |
||||
|
And I set the following fields to these values: |
||||
|
| id_grade_modgrade_type | Point | |
||||
|
| id_grade_modgrade_point | 50 | |
||||
|
And I press "Save and display" |
||||
|
|
||||
|
When I click on "Take attendance" "link" in the "01:00 - 02:00" "table_row" |
||||
|
# Late |
||||
|
And I click on "td.c3 input" "css_element" in the "Student 1" "table_row" |
||||
|
And I press "Save attendance" |
||||
|
|
||||
|
When I follow "Add session" |
||||
|
And I set the following fields to these values: |
||||
|
| id_sestime_starthour | 03 | |
||||
|
| id_sestime_endhour | 04 | |
||||
|
And I click on "id_submitbutton" "button" |
||||
|
|
||||
|
When I click on "Take attendance" "link" in the "03:00 - 04:00" "table_row" |
||||
|
# Present |
||||
|
And I click on "td.c2 input" "css_element" in the "Student 1" "table_row" |
||||
|
And I press "Save attendance" |
||||
|
|
||||
|
When I follow "Add session" |
||||
|
And I set the following fields to these values: |
||||
|
| id_sestime_starthour | 05 | |
||||
|
| id_sestime_endhour | 06 | |
||||
|
And I click on "id_submitbutton" "button" |
||||
|
|
||||
|
Then I log out |
||||
|
|
||||
|
When I log in as "student1" |
||||
|
And I follow "Course 1" |
||||
|
And I follow "Attendance" |
||||
|
And I follow "All" |
||||
|
|
||||
|
Then "2" "text" should exist in the "Taked sessions" "table_row" |
||||
|
And "3 / 4" "text" should exist in the "Points over taked sessions:" "table_row" |
||||
|
And "75.0%" "text" should exist in the "Percentage over taked sessions:" "table_row" |
||||
|
And "3" "text" should exist in the "Total number of sessions:" "table_row" |
||||
|
And "3 / 6" "text" should exist in the "Points over all sessions:" "table_row" |
||||
|
And "50.0%" "text" should exist in the "Percentage over all sessions:" "table_row" |
||||
|
And "5 / 6" "text" should exist in the "Maximum possible points:" "table_row" |
||||
|
And "83.3%" "text" should exist in the "Maximum possible percentage:" "table_row" |
||||
|
|
||||
|
And I log out |
Loading…
Reference in new issue