Conditional activities: Difference between revisions
Helen Foster (talk | contribs) |
|||
Line 1: | Line 1: | ||
{{Moodle_2.0}} | {{Moodle_2.0}} | ||
= Design document = | = Design document = | ||
(This is a design document by sam marshall from the Open University. It is based on earlier discussion in this wiki, and then detailed discussion with moodle.com staff who contributed improvements and corrections.) | (This is a design document by sam marshall from the Open University. It is based on earlier discussion in this wiki, and then detailed discussion with moodle.com staff who contributed improvements and corrections.) | ||
Line 8: | Line 6: | ||
sam marshall, 21 May 2008; updated as of 26 June 2008. Exported to MediaWiki format using OpenOffice.org 3.0 beta (i.e. this page doesn't perfectly represent the word-processor version) and manually tweaked a bit to fix it where it was obviously wrong. | sam marshall, 21 May 2008; updated as of 26 June 2008. Exported to MediaWiki format using OpenOffice.org 3.0 beta (i.e. this page doesn't perfectly represent the word-processor version) and manually tweaked a bit to fix it where it was obviously wrong. | ||
== Introduction == | == Introduction == | ||
This design document describes in some detail a proposed method to add support for ‘conditional activities’ to Moodle. It is based on a [https://docs.moodle.org/en/Development:Conditional_activities discussion on the Moodle wiki], conversations with Moodle.com staff, and only the teeniest pinch of OU requirements. | This design document describes in some detail a proposed method to add support for ‘conditional activities’ to Moodle. It is based on a [https://docs.moodle.org/en/Development:Conditional_activities discussion on the Moodle wiki], conversations with Moodle.com staff, and only the teeniest pinch of OU requirements. | ||
This is divided into two related, but separate, chunks of work. | This is divided into two related, but separate, chunks of work. | ||
=== Completion tracking === | === Completion tracking === | ||
Make the system store whether or not an activity has been ‘completed’. | Make the system store whether or not an activity has been ‘completed’. | ||
Line 22: | Line 18: | ||
It should be possible for teachers to access progress information for their students, so that they can see if anyone is falling behind. | It should be possible for teachers to access progress information for their students, so that they can see if anyone is falling behind. | ||
=== Conditional availability === | === Conditional availability === | ||
Allow or prevent access to an activity depending on various conditions. | Allow or prevent access to an activity depending on various conditions. | ||
These conditions may include the completion of other activities; in the case of graded activities, also whether the grade was pass/fail, or a specific amount. It also may include date. | These conditions may include the completion of other activities; in the case of graded activities, also whether the grade was pass/fail, or a specific amount. It also may include date. | ||
=== Development process === | === Development process === | ||
I will do this work here. It is possible that time constraints might mean I only do the first part (completion tracking). | I will do this work here. It is possible that time constraints might mean I only do the first part (completion tracking). | ||
Line 36: | Line 30: | ||
In some cases the OU have versions of these features. I will be coding automatic upgrade from the previous versions. This will not be included in the core Moodle 2.0 version. | In some cases the OU have versions of these features. I will be coding automatic upgrade from the previous versions. This will not be included in the core Moodle 2.0 version. | ||
== Completion tracking == | == Completion tracking == | ||
=== Completion options === | === Completion options === | ||
The completion system can be enabled or disabled at site, course, and activity level. | The completion system can be enabled or disabled at site, course, and activity level. | ||
* At site level, the new admin variable $CFG->enablecompletion (defaults to 1?). | * At site level, the new admin variable $CFG->enablecompletion (defaults to 1?). | ||
* At course level, a new mdl_course field enablecompletion (defaults to 1). | * At course level, a new mdl_course field enablecompletion (defaults to 1). | ||
* At activity level, a new mdl_course_modules field completion with values 0 = none, 1 = manual (student decides when they’ve completed something), 2 = automatic. Defaults to 1 but may be set by module e.g. a quiz module could default to automatic, label could set it to 0 so you don’t get checkboxes beside each label, etc. | * At activity level, a new mdl_course_modules field completion with values 0 = none, 1 = manual (student decides when they’ve completed something), 2 = automatic. Defaults to 1 but may be set by module e.g. a quiz module could default to automatic, label could set it to 0 so you don’t get checkboxes beside each label, etc. | ||
This table illustrates the effect of these options. (‘enablecompletion’ is abbreviated to ‘ec’.) | This table illustrates the effect of these options. (‘enablecompletion’ is abbreviated to ‘ec’.) | ||
Line 52: | Line 43: | ||
| '''Feature''' | | '''Feature''' | ||
| '''Appears if''' | | '''Appears if''' | ||
|- | |- | ||
| Admin settings | | Admin settings | ||
| On-off toggle for $CFG->ec | | On-off toggle for $CFG->ec | ||
| – | | – | ||
|- | |- | ||
| Course settings | | Course settings | ||
| On-off toggle for course ec | | On-off toggle for course ec | ||
| $CFG->ec | | $CFG->ec | ||
|- | |- | ||
| Activity settings | | Activity settings | ||
| Off/manual/automatic option for course-module completion | | Off/manual/automatic option for course-module completion | ||
| $CFG->ec && course ec | | $CFG->ec && course ec | ||
|- | |- | ||
| Course view | | Course view | ||
| Completion display/controls against activity | | Completion display/controls against activity | ||
| $CFG->ec && course ec && completion | | $CFG->ec && course ec && completion | ||
|- | |- | ||
| Admin block | | Admin block | ||
| Link to progress report | | Link to progress report | ||
| $CFG->ec && course ec && user has permission | | $CFG->ec && course ec && user has permission | ||
|} | |} | ||
=== Completion states and conditions === | === Completion states and conditions === | ||
Completion state is stored per-user for every activity. There are four states: | Completion state is stored per-user for every activity. There are four states: | ||
* <nowiki>Not completed [default – not stored in database]</nowiki> | * <nowiki>Not completed [default – not stored in database]</nowiki> | ||
* Completed (pass/fail unspecified) | * Completed (pass/fail unspecified) | ||
* Completed, passed | * Completed, passed | ||
* Completed, failed | * Completed, failed | ||
The final two states only apply when completion is based on a specific grade result. These are used only in some situations. Here are the rules: | The final two states only apply when completion is based on a specific grade result. These are used only in some situations. Here are the rules: | ||
* Grade visible, ‘grade to pass’ set: ‘completed, passed’ and ‘completed, failed’ states will be used. | * Grade visible, ‘grade to pass’ set: ‘completed, passed’ and ‘completed, failed’ states will be used. | ||
* ‘Grade to pass’ not set ''or''grade is hidden ''or''grade is hidden-until (regardless of until date): only the standard ‘not completed’, ‘completed’ states are used. | * ‘Grade to pass’ not set ''or''grade is hidden ''or''grade is hidden-until (regardless of until date): only the standard ‘not completed’, ‘completed’ states are used. | ||
This is a ‘push’ system – the state is not computed live but is saved and that value used. When completion for the activity is set to manual, students can toggle this value between not completed and completed. When it is set to automatic, the system adjusts the value in certain cases. | This is a ‘push’ system – the state is not computed live but is saved and that value used. When completion for the activity is set to manual, students can toggle this value between not completed and completed. When it is set to automatic, the system adjusts the value in certain cases. | ||
==== Standard conditions ==== | ==== Standard conditions ==== | ||
There are two standard conditions which do not require (much) module-specific behaviour. | There are two standard conditions which do not require (much) module-specific behaviour. | ||
* Graded – module has assigned grade for student. | * Graded – module has assigned grade for student. | ||
** If there are multiple grades for this activity, you can select which one is used to determine completion. (We will not implement this selection in the user interface for the first release. It will always use the first grade.) | ** If there are multiple grades for this activity, you can select which one is used to determine completion. (We will not implement this selection in the user interface for the first release. It will always use the first grade.) | ||
Line 102: | Line 81: | ||
* Viewed – student has viewed module. | * Viewed – student has viewed module. | ||
** For this to be supported, the module must call a function completion_set_module_viewed($cm) when it thinks that the user has ‘viewed’ the activity. It also needs to indicate that it supports it via ''module''_supports(FEATURE_COMPLETION_TRACKS_VIEWS). | ** For this to be supported, the module must call a function completion_set_module_viewed($cm) when it thinks that the user has ‘viewed’ the activity. It also needs to indicate that it supports it via ''module''_supports(FEATURE_COMPLETION_TRACKS_VIEWS). | ||
==== Custom conditions ==== | ==== Custom conditions ==== | ||
Modules can support arbitrary custom conditions (with their own form components to configure these, and their own data storage to track them). | Modules can support arbitrary custom conditions (with their own form components to configure these, and their own data storage to track them). | ||
Example conditions might be: | Example conditions might be: | ||
* Forum | * Forum | ||
** User has made N posts. | ** User has made N posts. | ||
Line 117: | Line 94: | ||
* Choice | * Choice | ||
** User has voted. | ** User has voted. | ||
It is up to the module to determine when a condition has been met and update the user’s completion. | It is up to the module to determine when a condition has been met and update the user’s completion. | ||
As part of this project I plan to create some custom conditions for one or a few modules (probably just forum), and implement view tracking for a wider range of modules. | As part of this project I plan to create some custom conditions for one or a few modules (probably just forum), and implement view tracking for a wider range of modules. | ||
==== Combining conditions ==== | ==== Combining conditions ==== | ||
If an activity has both the standard grade condition, and module conditions, these are currently combined via Boolean AND. Modules that support multiple conditions should usually also AND them as this will make life simpler for developer and users; however this is up to the module, as it creates its own form fields and data items. | If an activity has both the standard grade condition, and module conditions, these are currently combined via Boolean AND. Modules that support multiple conditions should usually also AND them as this will make life simpler for developer and users; however this is up to the module, as it creates its own form fields and data items. | ||
In the future we may (or may not!) provide the ability to choose boolean OR instead. Some of the API functions contain a parameter that indicates how results should be combined. At present this is always set to AND. | In the future we may (or may not!) provide the ability to choose boolean OR instead. Some of the API functions contain a parameter that indicates how results should be combined. At present this is always set to AND. | ||
=== Expected date === | === Expected date === | ||
An activity can optionally have an expected completion date. This date currently has no effect and is not shown to students, but it appears to teachers when viewing progress. It's intended so that teachers can see when students are having problems and maybe offer assistance. | An activity can optionally have an expected completion date. This date currently has no effect and is not shown to students, but it appears to teachers when viewing progress. It's intended so that teachers can see when students are having problems and maybe offer assistance. | ||
In future it might be possible to export this data – e.g. the list of students who are 'late' – to external systemss. | In future it might be possible to export this data – e.g. the list of students who are 'late' – to external systemss. | ||
=== Database === | === Database === | ||
(''Prefix is shown as _. Constants are defined for all values here.'') | (''Prefix is shown as _. Constants are defined for all values here.'') | ||
* _course | * _course | ||
** +Field enablecompletion, unsigned int (1) default 0 not null.1 = enable completion options for activities (if enabled at site level). This is the user-interface default that applies to new courses when completion is enabled for the site.0 = disable and hide options. This is the database default that will apply to existing courses. | ** +Field enablecompletion, unsigned int (1) default 0 not null.1 = enable completion options for activities (if enabled at site level). This is the user-interface default that applies to new courses when completion is enabled for the site.0 = disable and hide options. This is the database default that will apply to existing courses. | ||
Line 149: | Line 121: | ||
** viewed, unsigned int(1)null = not tracked0 = not viewed1 = viewedOnly stored if the activity is tracking viewed state. | ** viewed, unsigned int(1)null = not tracked0 = not viewed1 = viewedOnly stored if the activity is tracking viewed state. | ||
** timemodified, unsigned int (10) not null.Last date the state changed, in seconds since epoch. | ** timemodified, unsigned int (10) not null.Last date the state changed, in seconds since epoch. | ||
=== Capabilities === | === Capabilities === | ||
* moodle/course:viewprogress<nowiki> [default Teacher, Editing Teacher, Course Creator]</nowiki>Users with this permission can view progress of students on the course. If the course is set to visible groups mode, or the user also has accessallgroups, then they can see all groups. Otherwise they can only see groups they belong to. | * moodle/course:viewprogress<nowiki> [default Teacher, Editing Teacher, Course Creator]</nowiki>Users with this permission can view progress of students on the course. If the course is set to visible groups mode, or the user also has accessallgroups, then they can see all groups. Otherwise they can only see groups they belong to. | ||
=== Admin === | === Admin === | ||
A new admin setting progresstrackedroles stores a list of the roles that are considered relevant when displaying progress. (Other roles can still use the completion system, but won’t be shown on the progress screen.) This setting is editable via standard admin screens. | A new admin setting progresstrackedroles stores a list of the roles that are considered relevant when displaying progress. (Other roles can still use the completion system, but won’t be shown on the progress screen.) This setting is editable via standard admin screens. | ||
=== API === | === API === | ||
These functions will be included in a completionlib.php. | These functions will be included in a completionlib.php. | ||
* completion_is_enabled($course=null,$cm=null)Returns true if completion is enabled. With no parameters, returns the site value; when course is specified, checks course as well.If course-module is specified, the return value is the same as the value of completion from course_modules. | * completion_is_enabled($course=null,$cm=null)Returns true if completion is enabled. With no parameters, returns the site value; when course is specified, checks course as well.If course-module is specified, the return value is the same as the value of completion from course_modules. | ||
* completion_update_state($course,$cm, $possibleresult=COMPLETION_UNKNOWN,$userid=0)Called to update completion state on the activity $cm for the given or current user. This obtains grade/viewable information if necessary and then asks the module whether the activity has been completed.It is called whenever a grade is updated on an activity that uses grades for completion and, by modules, whenever a module-specific piece of data that might affect completion has changed. | * completion_update_state($course,$cm, $possibleresult=COMPLETION_UNKNOWN,$userid=0)Called to update completion state on the activity $cm for the given or current user. This obtains grade/viewable information if necessary and then asks the module whether the activity has been completed.It is called whenever a grade is updated on an activity that uses grades for completion and, by modules, whenever a module-specific piece of data that might affect completion has changed. | ||
Line 172: | Line 140: | ||
* completion_get_progress_all($course,$sortfirstname=false,$groupid=0)Obtains progress of all users in a course (or group) across all activities in that course for which completion tracking is enabled. (''Used by the progress report.'') | * completion_get_progress_all($course,$sortfirstname=false,$groupid=0)Obtains progress of all users in a course (or group) across all activities in that course for which completion tracking is enabled. (''Used by the progress report.'') | ||
* completion_inform_grade_changed($course,$cm,&$item,&$grade,$deleted)Called to notify the completion system when a user's grade changes. Does nothing (quickly) if completion is not enabled for the item; if completion is enabled and depends on grade, calls completion_update_state. (''Provided only for use by the gradebook.'') | * completion_inform_grade_changed($course,$cm,&$item,&$grade,$deleted)Called to notify the completion system when a user's grade changes. Does nothing (quickly) if completion is not enabled for the item; if completion is enabled and depends on grade, calls completion_update_state. (''Provided only for use by the gradebook.'') | ||
=== Module changes === | === Module changes === | ||
There is no requirement for any module changes to support the completion system. Existing modules continue to work. | There is no requirement for any module changes to support the completion system. Existing modules continue to work. | ||
Line 179: | Line 146: | ||
Progressively more changes are required when implementing more detailed completion support for a module. | Progressively more changes are required when implementing more detailed completion support for a module. | ||
==== View support ==== | ==== View support ==== | ||
To support the 'complete when viewed' feature, a module must do the following: | To support the 'complete when viewed' feature, a module must do the following: | ||
* Implement ''module''_supports() as follows:function ''module''<nowiki>_supports($feature) { switch($feature) { case FEATURE_COMPLETION_TRACKS_VIEWS: return true; default: return false; }}</nowiki> | |||
* Implement ''module''_supports() as follows:function ''module''_supports($feature) { switch($feature) { case FEATURE_COMPLETION_TRACKS_VIEWS: return true; default: | |||
* Add calls to completion_set_module_viewed whenever the module considers that it has been 'viewed'. | * Add calls to completion_set_module_viewed whenever the module considers that it has been 'viewed'. | ||
** It is up to the module to determine what this means. However most modules might put this call in view.php, near print_footer once it is clear that no errors occurred. | ** It is up to the module to determine what this means. However most modules might put this call in view.php, near print_footer once it is clear that no errors occurred. | ||
** This function does not take a significant time to run if view-based completion is not enabled, so you don't need to put the call inside an if. | ** This function does not take a significant time to run if view-based completion is not enabled, so you don't need to put the call inside an if. | ||
==== Grade support ==== | ==== Grade support ==== | ||
If a module provides grades, making ''module''_supports() return true for FEATURE_GRADE_HAS_GRADES will make these accessible to the completion system. | If a module provides grades, making ''module''_supports() return true for FEATURE_GRADE_HAS_GRADES will make these accessible to the completion system. | ||
==== Custom completion ==== | ==== Custom completion ==== | ||
Supporting module-specific custom completion conditions requires extra work: | Supporting module-specific custom completion conditions requires extra work: | ||
* Decide how to store the settings for these extra conditions (probably in your module's main table). Change your database tables to allow this. | * Decide how to store the settings for these extra conditions (probably in your module's main table). Change your database tables to allow this. | ||
* Add FEATURE_COMPLETION_HAS_RULES to your ''module''_supports(). | * Add FEATURE_COMPLETION_HAS_RULES to your ''module''_supports(). | ||
* Add the extra controls to your mod_form.php. | * Add the extra controls to your mod_form.php. | ||
** Override the method | ** Override the method add_completion_rules() so that it adds extra form elements for your controls (the method is called at the right point so that they are added in the 'completion' box), and returns a list of the form elements (this is used to enable/disable them appropriately). | ||
** Override the function completion_rule_enabled($data) so that it returns true if the supplied data means that at least one of the module's completion conditions is turned on. This is used to prevent the user from choosing 'automatic' completion if they don't also enable at least one condition. | ** Override the function completion_rule_enabled($data) so that it returns true if the supplied data means that at least one of the module's completion conditions is turned on. This is used to prevent the user from choosing 'automatic' completion if they don't also enable at least one condition. | ||
** You may need to modify other functions such as definition_after_data() and get_data to set up your form controls appropriately based on the data from the database, or vice versa. | ** You may need to modify other functions such as definition_after_data() and get_data to set up your form controls appropriately based on the data from the database, or vice versa. | ||
Line 205: | Line 167: | ||
** If completion conditions are not enabled for this particular instance, the function should return $logic (not false). | ** If completion conditions are not enabled for this particular instance, the function should return $logic (not false). | ||
* In your module code, when something changes which might affect completion, call completion_update_state | * In your module code, when something changes which might affect completion, call completion_update_state | ||
=== Example of system operation === | === Example of system operation === | ||
Assume that the forum offers an option to check completion based on the number of posts (complete when you’ve made N posts). | Assume that the forum offers an option to check completion based on the number of posts (complete when you’ve made N posts). | ||
Every time a user makes a new post: | Every time a user makes a new post: | ||
* Forum checks if completion tracking based on the number of posts is enabled (this would probably be an option in $forum). If not, it does nothing (''stop''). | * Forum checks if completion tracking based on the number of posts is enabled (this would probably be an option in $forum). If not, it does nothing (''stop''). | ||
* Forum calls completion_update_state($cm,COMPLETION_COMPLETE). | * Forum calls completion_update_state($cm,COMPLETION_COMPLETE). | ||
Line 218: | Line 178: | ||
* The forum checks its own rules, including the number of posts and anything else that’s enabled. It returns true if these rules are met and false if they’re not. | * The forum checks its own rules, including the number of posts and anything else that’s enabled. It returns true if these rules are met and false if they’re not. | ||
* Combining this data, the system decides whether to update the completion state. If an update is needed, it makes the change in the database. | * Combining this data, the system decides whether to update the completion state. If an update is needed, it makes the change in the database. | ||
=== Activity UI (course page) === | === Activity UI (course page) === | ||
The user interface for students on the course view page needs to allow for displaying progress to students and, where completion is set to manual, allowing students to tick their own progress boxes. | The user interface for students on the course view page needs to allow for displaying progress to students and, where completion is set to manual, allowing students to tick their own progress boxes. | ||
I have based this suggested interface on experience here at the OU. The interface will be implemented via changes to print_section and course view.php. | I have based this suggested interface on experience here at the OU. The interface will be implemented via changes to print_section and course view.php. | ||
* Completion displays alongside each activity for which completion is enabled, to the right of the section. (This conveniently separates it from the functional information at the left, and means that all the progress markers line up with each other.) | * Completion displays alongside each activity for which completion is enabled, to the right of the section. (This conveniently separates it from the functional information at the left, and means that all the progress markers line up with each other.) | ||
* Automatic completion displays as a tick or cross icon, by default coloured green and red (accessible colours will be chosen), or some kind of faint outline if something isn’t completed yet. The cross icon is used if completion state is 1. | * Automatic completion displays as a tick or cross icon, by default coloured green and red (accessible colours will be chosen), or some kind of faint outline if something isn’t completed yet. The cross icon is used if completion state is 1. | ||
Line 229: | Line 187: | ||
* If completion is not enabled for an activity (or for the course, site, etc) then the print_section display is the same as at present. | * If completion is not enabled for an activity (or for the course, site, etc) then the print_section display is the same as at present. | ||
* When editing is turned on, completion information always displays as ticked regardless of the user’s actual completion setting. This makes it easy to see that completion is enabled for that activity. | * When editing is turned on, completion information always displays as ticked regardless of the user’s actual completion setting. This makes it easy to see that completion is enabled for that activity. | ||
I will get a graphic designer to look at the icons to use. To reiterate, there are six icons: | I will get a graphic designer to look at the icons to use. To reiterate, there are six icons: | ||
* automatic completion, not completed yet (above, not actually shown on its own, but would be a faint grey dotted box) | * automatic completion, not completed yet (above, not actually shown on its own, but would be a faint grey dotted box) | ||
* automatic completion, completed (above, slightly grey tick, with faint grey dotted surround) | * automatic completion, completed (above, slightly grey tick, with faint grey dotted surround) | ||
Line 238: | Line 194: | ||
* manual completion, not completed (heavy black dotted outline) | * manual completion, not completed (heavy black dotted outline) | ||
* manual completion, completed (heavy black dotted outline with black tick) | * manual completion, completed (heavy black dotted outline with black tick) | ||
It may need some work to make the manual ones look clickable and the automatic ones look not clickable, but not irrelevant either. For example we might have to resort to crappy 3D button-style shading on the manual ones. This is what I've done (badly) in the initial version of the icons which I have made. | It may need some work to make the manual ones look clickable and the automatic ones look not clickable, but not irrelevant either. For example we might have to resort to crappy 3D button-style shading on the manual ones. This is what I've done (badly) in the initial version of the icons which I have made. | ||
=== Configuration UI (activity settings page) === | === Configuration UI (activity settings page) === | ||
Each activity’s completion settings can be configured on the standard activity settings page. These settings only appear if completion is enabled for the course and site. | Each activity’s completion settings can be configured on the standard activity settings page. These settings only appear if completion is enabled for the course and site. | ||
Line 249: | Line 203: | ||
((TODO: Diagram needs redoing)) | ((TODO: Diagram needs redoing)) | ||
* A dropdown allows choice of the three completion options – none, manual, automatic. (All three are shown in the diagrams below.) If the module does not support its own completion conditions, and does not support grades, then the ‘automatic’ option will not appear. | * A dropdown allows choice of the three completion options – none, manual, automatic. (All three are shown in the diagrams below.) If the module does not support its own completion conditions, and does not support grades, then the ‘automatic’ option will not appear. | ||
* A ‘view’ checkbox only appears if the module supports view tracking. If completion is not set to automatic, it will be greyed out. It allows you to mark something complete as soon as the user goes there once. | * A ‘view’ checkbox only appears if the module supports view tracking. If completion is not set to automatic, it will be greyed out. It allows you to mark something complete as soon as the user goes there once. | ||
Line 257: | Line 210: | ||
* <nowiki>An expected completion date (default disabled) is given. This can be enabled for manual or automatic completion. It has no practical effect but displays on the progress screen. The intention is that those who design a course can set these dates at key points in the course. During the course, teachers can look at the progress report and use the dates as a guideline to check whether students are falling behind. [At a later date it might be possible to do other things with this data, such as export a list of 'late' students to an external system.]</nowiki> | * <nowiki>An expected completion date (default disabled) is given. This can be enabled for manual or automatic completion. It has no practical effect but displays on the progress screen. The intention is that those who design a course can set these dates at key points in the course. During the course, teachers can look at the progress report and use the dates as a guideline to check whether students are falling behind. [At a later date it might be possible to do other things with this data, such as export a list of 'late' students to an external system.]</nowiki> | ||
* If anybody already has stored completion state for this activity, completion settings will be locked: they appear, but read-only. A button allows you to unlock the settings (making those fields editable again); after you do that and save the form, existing completion data is wiped and recalculated against the new conditions. A warning by the button explains that changing completion conditions after students complete things is not a good idea. | * If anybody already has stored completion state for this activity, completion settings will be locked: they appear, but read-only. A button allows you to unlock the settings (making those fields editable again); after you do that and save the form, existing completion data is wiped and recalculated against the new conditions. A warning by the button explains that changing completion conditions after students complete things is not a good idea. | ||
=== Progress tracking UI === | === Progress tracking UI === | ||
Teachers wishing to track student progress can do so via the admin block. The existing course reports page will include a link to view student progress if the user has viewprogress capability. | Teachers wishing to track student progress can do so via the admin block. The existing course reports page will include a link to view student progress if the user has viewprogress capability. | ||
The resulting page shows a summary of progress either for a particular group, or for all students in the course, according to the normal rules for group selection. It may include a standard group dropdown too. | The resulting page shows a summary of progress either for a particular group, or for all students in the course, according to the normal rules for group selection. It may include a standard group dropdown too. | ||
# Progress is shown in a table. Students (everyone with a role in progresstrackedroles<nowiki>) are displayed down the left of the table and for activities that have completion enabled, the activity names [with expected completion dates, if set] are displayed across the top. Students can be sorted by first name or last name. The student names link to profiles and activity names link to the activities.</nowiki> | # Progress is shown in a table. Students (everyone with a role in progresstrackedroles<nowiki>) are displayed down the left of the table and for activities that have completion enabled, the activity names [with expected completion dates, if set] are displayed across the top. Students can be sorted by first name or last name. The student names link to profiles and activity names link to the activities.</nowiki> | ||
# The cells in this grid show progress indicators using the same icons as used on the course view page, although these icons are not clickable in the report. For each cell, the title, which you can see by hovering over it, indicates the state of the cell and the time modified (‘Completed 12/9/08 13:47’) as well as the student's name and the activity name (in case you are scrolling around a table that doesn't fit on-screen). | # The cells in this grid show progress indicators using the same icons as used on the course view page, although these icons are not clickable in the report. For each cell, the title, which you can see by hovering over it, indicates the state of the cell and the time modified (‘Completed 12/9/08 13:47’) as well as the student's name and the activity name (in case you are scrolling around a table that doesn't fit on-screen). | ||
# A link at the bottom allows this table to be downloaded in CSV format. The downloaded version contains the same data, using two columns (‘state’ and ‘date’) for each activity. | # A link at the bottom allows this table to be downloaded in CSV format. The downloaded version contains the same data, using two columns (‘state’ and ‘date’) for each activity. | ||
=== Performance === | === Performance === | ||
==== Course view ==== | ==== Course view ==== | ||
When completion is enabled for a course, the course view page needs to obtain completion information. This will be cached in session and retrieved efficiently (hopefully 1 query) the first time. | When completion is enabled for a course, the course view page needs to obtain completion information. This will be cached in session and retrieved efficiently (hopefully 1 query) the first time. | ||
==== Module pages ==== | ==== Module pages ==== | ||
There is no performance impact when using modules that do not support completion, or where completion is disabled. | There is no performance impact when using modules that do not support completion, or where completion is disabled. | ||
Line 279: | Line 228: | ||
View-related completion tracking, the part most potentially problematic, will behave similarly: the first time you view something that has a 'viewed' requirement, it will make extra queries as it marks it viewed (or, if you viewed it in a previous session, loads up that information). After that the information will be cached in your session. | View-related completion tracking, the part most potentially problematic, will behave similarly: the first time you view something that has a 'viewed' requirement, it will make extra queries as it marks it viewed (or, if you viewed it in a previous session, loads up that information). After that the information will be cached in your session. | ||
=== Backup and restore === | === Backup and restore === | ||
* When users are included in backup, course backup will include the contents of the _course_modules_completion table. | * When users are included in backup, course backup will include the contents of the _course_modules_completion table. | ||
* Course and course-modules backup will be modified to include the new fields in those tables. | * Course and course-modules backup will be modified to include the new fields in those tables. | ||
== Conditional availability == | == Conditional availability == | ||
=== Conditional options === | === Conditional options === | ||
There is no specific option to enable this part of the feature (?). The parts which depend on the completion system are enabled using the completion flag. | There is no specific option to enable this part of the feature (?). The parts which depend on the completion system are enabled using the completion flag. | ||
=== Available conditions === | === Available conditions === | ||
You can place conditions on any activity. Conditions are always combined with Boolean AND, i.e. all conditions must be met before the activity becomes available. Unlike completion, conditions are not module-dependent. There are two types of condition: | You can place conditions on any activity. Conditions are always combined with Boolean AND, i.e. all conditions must be met before the activity becomes available. Unlike completion, conditions are not module-dependent. There are two types of condition: | ||
# Conditional on date. You can have both of these conditions if required. | # Conditional on date. You can have both of these conditions if required. | ||
#* On or after date – activity becomes available on given date. | #* On or after date – activity becomes available on given date. | ||
Line 298: | Line 243: | ||
#* Activity must be completed and passed – completion must have been graded and displayed with a pass mark (tick icon). | #* Activity must be completed and passed – completion must have been graded and displayed with a pass mark (tick icon). | ||
#* Activity must be graded at least/at most ''N''. | #* Activity must be graded at least/at most ''N''. | ||
=== Database === | === Database === | ||
* _course_modules | * _course_modules | ||
Line 311: | Line 255: | ||
** gradesign, varchar(2).NULL = no required grade.<nowiki>‘<’, ‘<=</nowiki>’, ‘>’, ‘>=’ = requirement for grade. | ** gradesign, varchar(2).NULL = no required grade.<nowiki>‘<’, ‘<=</nowiki>’, ‘>’, ‘>=’ = requirement for grade. | ||
** requiredgrade, number(10,5 decimals).Grade boundary used together with the above sign. May be null. | ** requiredgrade, number(10,5 decimals).Grade boundary used together with the above sign. May be null. | ||
=== API === | === API === | ||
Two new functions: | Two new functions: | ||
* availability_is_available($cm)Returns true if the module is available to students (it is visible, plus availability conditions, if any, are met). Does not include course access conditions, which it assumes have already been checked.This is a slot-in replacement where code checks for $cm->visible at key points such as in require_login. | * availability_is_available($cm)Returns true if the module is available to students (it is visible, plus availability conditions, if any, are met). Does not include course access conditions, which it assumes have already been checked.This is a slot-in replacement where code checks for $cm->visible at key points such as in require_login. | ||
* availability_get_display_details($cm)Obtains information about the activity’s availability which is required in order to display (or not display) a link to the activity. Returns an object with the following fields:->available – If true, activity is available; users should be allowed to access it / get links to it.->show – If true, activity should be displayed (even to users who do not have viewhiddenactivities)->info – Informational string. Blank if the activity is available. | * availability_get_display_details($cm)Obtains information about the activity’s availability which is required in order to display (or not display) a link to the activity. Returns an object with the following fields:->available – If true, activity is available; users should be allowed to access it / get links to it.->show – If true, activity should be displayed (even to users who do not have viewhiddenactivities)->info – Informational string. Blank if the activity is available. | ||
Other changes: | Other changes: | ||
* For performance reasons we need to cache the conditions in _course_modules_available. Best option is to use existing get_fast_modinfo infrastructure. This should not be hard. The above two functions will use this cache. | * For performance reasons we need to cache the conditions in _course_modules_available. Best option is to use existing get_fast_modinfo infrastructure. This should not be hard. The above two functions will use this cache. | ||
=== Configuration UI (activity settings page) === | === Configuration UI (activity settings page) === | ||
The configuration UI will be implemented as part of standard_coursemodule_elements in the module forms. The existing ‘visible to students’ option (not changed in database/code) is moved within this UI. | The configuration UI will be implemented as part of standard_coursemodule_elements in the module forms. The existing ‘visible to students’ option (not changed in database/code) is moved within this UI. | ||
Line 330: | Line 269: | ||
[[Image:]] | [[Image:]] | ||
* The actual ‘available from’ options should include time as well as date. ‘Available from’ should default to midnight tomorrow; ‘Available until’ should default to 23:59 today. (I got bored laying out combo boxes.) | * The actual ‘available from’ options should include time as well as date. ‘Available from’ should default to midnight tomorrow; ‘Available until’ should default to 23:59 today. (I got bored laying out combo boxes.) | ||
* ‘Information display’ controls whether informational text is displayed to students when an activity is not available. (See below.) The default is not to show information. | * ‘Information display’ controls whether informational text is displayed to students when an activity is not available. (See below.) The default is not to show information. | ||
Line 340: | Line 278: | ||
** The grade conditions appear only if the activity has a grade item. | ** The grade conditions appear only if the activity has a grade item. | ||
* The grade box is a text-entry field. Users type in the floating-point number version of the required grade. | * The grade box is a text-entry field. Users type in the floating-point number version of the required grade. | ||
=== Activity UI (course page) === | === Activity UI (course page) === | ||
(This will be accomplished via code changes to print_section. Logic is basically the same as for the current visible flag.) | (This will be accomplished via code changes to print_section. Logic is basically the same as for the current visible flag.) | ||
For available activities, the display obviously does not change. Unavailable activities will be displayed as follows: | For available activities, the display obviously does not change. Unavailable activities will be displayed as follows: | ||
* If the current user has viewhiddenactivities: | * If the current user has viewhiddenactivities: | ||
** The activity displays using the CSS style for hidden activities. | ** The activity displays using the CSS style for hidden activities. | ||
Line 352: | Line 288: | ||
** If showavailability is not set, or if the activity is actually hidden (visibility 0), the activity does not display at all. | ** If showavailability is not set, or if the activity is actually hidden (visibility 0), the activity does not display at all. | ||
** If showavailability is set and the activity isn’t hidden but is unavailable for some other reason, the name of the activity displays using the CSS style for hidden activities, but does not include an actual link to the activity. The informational message as to why the activity isn’t available is displayed. | ** If showavailability is set and the activity isn’t hidden but is unavailable for some other reason, the name of the activity displays using the CSS style for hidden activities, but does not include an actual link to the activity. The informational message as to why the activity isn’t available is displayed. | ||
Here are some examples of hidden activities with informational text:Assignment resources Available from 6 Oct 2008Assignment resources Available when Unit 1 Test grade is > 90Assignment resources Available when Tutor group forum is marked complete (+ other requirements)When there are multiple conditions, only one is shown. Date is considered first; the order after that is arbitrary. | Here are some examples of hidden activities with informational text:Assignment resources Available from 6 Oct 2008Assignment resources Available when Unit 1 Test grade is > 90Assignment resources Available when Tutor group forum is marked complete (+ other requirements)When there are multiple conditions, only one is shown. Date is considered first; the order after that is arbitrary. | ||
Behaviour is the same when editing is turned on except that the ‘availability’ string moves to the line below so as not to clash with all those icons. | Behaviour is the same when editing is turned on except that the ‘availability’ string moves to the line below so as not to clash with all those icons. | ||
=== Performance === | === Performance === | ||
This adds a single quick database query to the course view page for courses which have enabled conditional activities / completion. | This adds a single quick database query to the course view page for courses which have enabled conditional activities / completion. | ||
Line 363: | Line 297: | ||
I don’t believe this will pose a massive performance issue as it only applies when modules are used as source for this kind of information. We should review this once it’s developed and, if necessary, optimise performance then. There are various caching approaches we could use. | I don’t believe this will pose a massive performance issue as it only applies when modules are used as source for this kind of information. We should review this once it’s developed and, if necessary, optimise performance then. There are various caching approaches we could use. | ||
=== Module delete === | === Module delete === | ||
If you try to delete a module, it will check to see if that module is referenced by any other module as a condition. If that’s the case, you will not be allowed to delete it. An error message will include a link to the module edit page for the other module (so you can go there and delete the condition if you like). | If you try to delete a module, it will check to see if that module is referenced by any other module as a condition. If that’s the case, you will not be allowed to delete it. An error message will include a link to the module edit page for the other module (so you can go there and delete the condition if you like). | ||
=== Backup and restore === | === Backup and restore === | ||
* The new _course_modules_available table will be backed up and restored. | * The new _course_modules_available table will be backed up and restored. | ||
** Partial restore needs to be handled. If your backup includes module A but not module B, and module A had a condition on B, then that condition will not be restored. | ** Partial restore needs to be handled. If your backup includes module A but not module B, and module A had a condition on B, then that condition will not be restored. | ||
* Backup will also be modified to include the fields added to _course_modules. | * Backup will also be modified to include the fields added to _course_modules. | ||
* If you restore a course with a startdateoffset, it will offset the dates from the new _course_modules date fields. | * If you restore a course with a startdateoffset, it will offset the dates from the new _course_modules date fields. | ||
== Module supported features == | == Module supported features == | ||
As part of the completion system, I needed a way for modules to indicate support of certain features, so I propose a generic one which I have implemented: | As part of the completion system, I needed a way for modules to indicate support of certain features, so I propose a generic one which I have implemented: | ||
* A module API function ''module''_supports($feature) which returns false if the feature is not available, and true (or an object with more information, if needed for specific features) if it is. | * A module API function ''module''_supports($feature) which returns false if the feature is not available, and true (or an object with more information, if needed for specific features) if it is. | ||
* A standard API function module_supports($modulename,$feature) which works as follows: | * A standard API function module_supports($modulename,$feature) which works as follows: | ||
Line 385: | Line 315: | ||
** FEATURE_COMPLETION_HAS_RULES | ** FEATURE_COMPLETION_HAS_RULES | ||
* Other feature constants could be added as desired, e.g. FEATURE_CRON, etc. My initial implementation will include only the 'new' ones needed for this work. | * Other feature constants could be added as desired, e.g. FEATURE_CRON, etc. My initial implementation will include only the 'new' ones needed for this work. | ||
Note that this implementation would not be appropriate if modules were changed to be fully object-oriented. However I don't expect that to happen in Moodle 2 so this is probably OK. | Note that this implementation would not be appropriate if modules were changed to be fully object-oriented. However I don't expect that to happen in Moodle 2 so this is probably OK. | ||
==See also== | ==See also== | ||
* [[Conditional activities_Adding module support]] | * [[Conditional activities_Adding module support]] | ||
* [[Conditional activities]] | * [[Conditional activities]] | ||
[[Category:Conditional activities]] | [[Category:Conditional activities]] | ||
[[Category:Completion]] | [[Category:Completion]] |
Latest revision as of 19:08, 22 October 2021
Moodle 2.0
Design document
(This is a design document by sam marshall from the Open University. It is based on earlier discussion in this wiki, and then detailed discussion with moodle.com staff who contributed improvements and corrections.)
See MDL-15497 for tasks and tracking.
sam marshall, 21 May 2008; updated as of 26 June 2008. Exported to MediaWiki format using OpenOffice.org 3.0 beta (i.e. this page doesn't perfectly represent the word-processor version) and manually tweaked a bit to fix it where it was obviously wrong.
Introduction
This design document describes in some detail a proposed method to add support for ‘conditional activities’ to Moodle. It is based on a discussion on the Moodle wiki, conversations with Moodle.com staff, and only the teeniest pinch of OU requirements.
This is divided into two related, but separate, chunks of work.
Completion tracking
Make the system store whether or not an activity has been ‘completed’.
This may be according to an activity-specific definition of completion, or because the student has ticked a box saying they’ve finished it.
When tracked automatically, completion could vary from formal requirements such as ‘scoring 90% on this quiz’ to informal requirements intended to ensure participation such as ‘post at least 3 times on this forum’.
It should be possible for teachers to access progress information for their students, so that they can see if anyone is falling behind.
Conditional availability
Allow or prevent access to an activity depending on various conditions.
These conditions may include the completion of other activities; in the case of graded activities, also whether the grade was pass/fail, or a specific amount. It also may include date.
Development process
I will do this work here. It is possible that time constraints might mean I only do the first part (completion tracking).
Development will be against Moodle 1.9, because we need it here at the OU, but it will never actually be committed into Moodle 1.9. The code will instead be ported to Moodle 2.0, which will require various changes (particularly in the area of database access).
Code will be PHP5. We will primarily test against Postgres here but intend using standard Moodle database API and only simple SQL where needed, so database compatibility is unlikely to be a problem.
In some cases the OU have versions of these features. I will be coding automatic upgrade from the previous versions. This will not be included in the core Moodle 2.0 version.
Completion tracking
Completion options
The completion system can be enabled or disabled at site, course, and activity level.
- At site level, the new admin variable $CFG->enablecompletion (defaults to 1?).
- At course level, a new mdl_course field enablecompletion (defaults to 1).
- At activity level, a new mdl_course_modules field completion with values 0 = none, 1 = manual (student decides when they’ve completed something), 2 = automatic. Defaults to 1 but may be set by module e.g. a quiz module could default to automatic, label could set it to 0 so you don’t get checkboxes beside each label, etc.
This table illustrates the effect of these options. (‘enablecompletion’ is abbreviated to ‘ec’.)
Location | Feature | Appears if |
Admin settings | On-off toggle for $CFG->ec | – |
Course settings | On-off toggle for course ec | $CFG->ec |
Activity settings | Off/manual/automatic option for course-module completion | $CFG->ec && course ec |
Course view | Completion display/controls against activity | $CFG->ec && course ec && completion |
Admin block | Link to progress report | $CFG->ec && course ec && user has permission |
Completion states and conditions
Completion state is stored per-user for every activity. There are four states:
- Not completed [default – not stored in database]
- Completed (pass/fail unspecified)
- Completed, passed
- Completed, failed
The final two states only apply when completion is based on a specific grade result. These are used only in some situations. Here are the rules:
- Grade visible, ‘grade to pass’ set: ‘completed, passed’ and ‘completed, failed’ states will be used.
- ‘Grade to pass’ not set orgrade is hidden orgrade is hidden-until (regardless of until date): only the standard ‘not completed’, ‘completed’ states are used.
This is a ‘push’ system – the state is not computed live but is saved and that value used. When completion for the activity is set to manual, students can toggle this value between not completed and completed. When it is set to automatic, the system adjusts the value in certain cases.
Standard conditions
There are two standard conditions which do not require (much) module-specific behaviour.
- Graded – module has assigned grade for student.
- If there are multiple grades for this activity, you can select which one is used to determine completion. (We will not implement this selection in the user interface for the first release. It will always use the first grade.)
- This condition is implemented by a hook in gradebook that runs at the point where a grade is set.
- Viewed – student has viewed module.
- For this to be supported, the module must call a function completion_set_module_viewed($cm) when it thinks that the user has ‘viewed’ the activity. It also needs to indicate that it supports it via module_supports(FEATURE_COMPLETION_TRACKS_VIEWS).
Custom conditions
Modules can support arbitrary custom conditions (with their own form components to configure these, and their own data storage to track them).
Example conditions might be:
- Forum
- User has made N posts.
- User has made N replies.
- Other people have posted N replies to discussions created by this user. (This an example of a more complex possibility, not necessarily something that would be a good idea.)
- Wiki
- User has edited N different pages.
- User has edited pages N times.
- Choice
- User has voted.
It is up to the module to determine when a condition has been met and update the user’s completion.
As part of this project I plan to create some custom conditions for one or a few modules (probably just forum), and implement view tracking for a wider range of modules.
Combining conditions
If an activity has both the standard grade condition, and module conditions, these are currently combined via Boolean AND. Modules that support multiple conditions should usually also AND them as this will make life simpler for developer and users; however this is up to the module, as it creates its own form fields and data items.
In the future we may (or may not!) provide the ability to choose boolean OR instead. Some of the API functions contain a parameter that indicates how results should be combined. At present this is always set to AND.
Expected date
An activity can optionally have an expected completion date. This date currently has no effect and is not shown to students, but it appears to teachers when viewing progress. It's intended so that teachers can see when students are having problems and maybe offer assistance.
In future it might be possible to export this data – e.g. the list of students who are 'late' – to external systemss.
Database
(Prefix is shown as _. Constants are defined for all values here.)
- _course
- +Field enablecompletion, unsigned int (1) default 0 not null.1 = enable completion options for activities (if enabled at site level). This is the user-interface default that applies to new courses when completion is enabled for the site.0 = disable and hide options. This is the database default that will apply to existing courses.
- _course_modules
- +Field completion, unsigned int (1) default 0 not null.0 = No progress tracking for this activity.1 = Manual completion tracking.2 = Automatic completion tracking.
- +Field completiongradeitemnumber, unsigned int(10) default 0.NULL = Grade information not used for completion.0,1,… = Use first/second/Nth grade item supplied by this activity.
- +Field completionview, unsigned int (1) default 0 not null.0 = View not required for completion.1 = View required for completion.
- +Field completionexpected, unsigned int (10) default 0 not null.0 = No particular date expected for completion* = time (seconds since epoch) by which activity is expected to be completed.
- New table _course_modules_completion which stores completion state for a user on each activity.
- id.
- coursemoduleid [index].
- userid [index].
- completionstate, unsigned int(1) not null.(The absence of a row in the table counts the same as 0 here.)0 = not completed.1 = completed.2 = completed, passed.3 = completed, failed.
- viewed, unsigned int(1)null = not tracked0 = not viewed1 = viewedOnly stored if the activity is tracking viewed state.
- timemodified, unsigned int (10) not null.Last date the state changed, in seconds since epoch.
Capabilities
- moodle/course:viewprogress [default Teacher, Editing Teacher, Course Creator]Users with this permission can view progress of students on the course. If the course is set to visible groups mode, or the user also has accessallgroups, then they can see all groups. Otherwise they can only see groups they belong to.
Admin
A new admin setting progresstrackedroles stores a list of the roles that are considered relevant when displaying progress. (Other roles can still use the completion system, but won’t be shown on the progress screen.) This setting is editable via standard admin screens.
API
These functions will be included in a completionlib.php.
- completion_is_enabled($course=null,$cm=null)Returns true if completion is enabled. With no parameters, returns the site value; when course is specified, checks course as well.If course-module is specified, the return value is the same as the value of completion from course_modules.
- completion_update_state($course,$cm, $possibleresult=COMPLETION_UNKNOWN,$userid=0)Called to update completion state on the activity $cm for the given or current user. This obtains grade/viewable information if necessary and then asks the module whether the activity has been completed.It is called whenever a grade is updated on an activity that uses grades for completion and, by modules, whenever a module-specific piece of data that might affect completion has changed.
- $possibleresult is included for performance reasons to avoid recalculating completion when not necessary. Set to COMPLETION_COMPLETE or COMPLETION_NOTCOMPLETE, it indicates that the change which necessitated calling this function can only result in that type of state. For example, if there is a condition that the user must make 5 forum posts, we would call this function in response to any new post. But if the state is already ‘complete’, there is no point going through counting posts, checking grades, etc. This hint allows the code to skip further work if the user’s state is already the target. Once retrieved we will cache the state in session so that frequently, no database queries are required.
- For performance reasons, modules should still only call this function when necessary. The forum should not call this function whenever a new post is made, unless the completion option for counting posts is actually turned on for that forum.
- When a module is set to manual completion, this function is used to directly toggle completion. The completion value is set to $possibleresult.
- completion_set_module_viewed($course,$cm,$userid=0)Called when a module is viewed. If view-based completion is enabled (in $cm) then it sets the 'viewed' flag and calls update_completion_state.
- completion_count_user_data($cm)Called to determine whether any users have already completed an activity (if so, returns the number). This is used by the module settings form to determine whether completion settings should be 'locked'.
- completion_delete_all_state($course,$cm)Called at the point where course-module entries are deleted. Deletes all completion state data for that course-module.
- completion_reset_all_state($course,$cm)Deletes existing completion state for all users in this activity, then recalculates it by calling update_completion_state a lot for (i) all state-tracked users (those with progresstrackedroles roles in this activity’s context), (ii) all users who have stored completion state for this activity.Needs to be called if completion conditions change.
- completion_get_data($course,$cm,$wholecourse=false,$userid=0)Obtains completion data for a particular user related to a given activity. User defaults to current user.The $wholecourse parameter is a hint that, if it isn't already available, the system should retrieve into cache the completion data for all course activities now (so that future requests for other activities can be satisfied from cache).
- completion_get_activities($course)Gets course-module objects for all activities on a course that have completion turned on. (Used by the progress report.)
- completion_get_progress_all($course,$sortfirstname=false,$groupid=0)Obtains progress of all users in a course (or group) across all activities in that course for which completion tracking is enabled. (Used by the progress report.)
- completion_inform_grade_changed($course,$cm,&$item,&$grade,$deleted)Called to notify the completion system when a user's grade changes. Does nothing (quickly) if completion is not enabled for the item; if completion is enabled and depends on grade, calls completion_update_state. (Provided only for use by the gradebook.)
Module changes
There is no requirement for any module changes to support the completion system. Existing modules continue to work.
If no changes are made to a module, then manual completion (where the user ticks the box themselves) is supported for activities of that type, and automatic completion is not offered as an option in the activity settings screen.
Progressively more changes are required when implementing more detailed completion support for a module.
View support
To support the 'complete when viewed' feature, a module must do the following:
- Implement module_supports() as follows:function module_supports($feature) { switch($feature) { case FEATURE_COMPLETION_TRACKS_VIEWS: return true; default: return false; }}
- Add calls to completion_set_module_viewed whenever the module considers that it has been 'viewed'.
- It is up to the module to determine what this means. However most modules might put this call in view.php, near print_footer once it is clear that no errors occurred.
- This function does not take a significant time to run if view-based completion is not enabled, so you don't need to put the call inside an if.
Grade support
If a module provides grades, making module_supports() return true for FEATURE_GRADE_HAS_GRADES will make these accessible to the completion system.
Custom completion
Supporting module-specific custom completion conditions requires extra work:
- Decide how to store the settings for these extra conditions (probably in your module's main table). Change your database tables to allow this.
- Add FEATURE_COMPLETION_HAS_RULES to your module_supports().
- Add the extra controls to your mod_form.php.
- Override the method add_completion_rules() so that it adds extra form elements for your controls (the method is called at the right point so that they are added in the 'completion' box), and returns a list of the form elements (this is used to enable/disable them appropriately).
- Override the function completion_rule_enabled($data) so that it returns true if the supplied data means that at least one of the module's completion conditions is turned on. This is used to prevent the user from choosing 'automatic' completion if they don't also enable at least one condition.
- You may need to modify other functions such as definition_after_data() and get_data to set up your form controls appropriately based on the data from the database, or vice versa.
- In your lib.php, implement the new function module_get_completion_state($course,$cm,$userid,$logic).
- If the specified module instance has completion requirements, this should return true (if they have been met) or false (if they haven't). The system will later combine this value with possible other completion requirements (view or grades).
- $logic is either COMPLETION_AND or COMPLETION_OR, indicating which type of Boolean logic should be used when there are multiple conditions.
- If completion conditions are not enabled for this particular instance, the function should return $logic (not false).
- In your module code, when something changes which might affect completion, call completion_update_state
Example of system operation
Assume that the forum offers an option to check completion based on the number of posts (complete when you’ve made N posts).
Every time a user makes a new post:
- Forum checks if completion tracking based on the number of posts is enabled (this would probably be an option in $forum). If not, it does nothing (stop).
- Forum calls completion_update_state($cm,COMPLETION_COMPLETE).
- System looks up the user’s current completion state for $cm. If the current state is already COMPLETION_COMPLETE (or COMPLETE_PASS or COMPLETE_FAIL) then it returns with no further action (stop).
- If grade-based completion is enabled, system obtains grade and checks it. If viewed-completion is enabled, system checks whether the module has been viewed.
- If the forum has its own completion rules, then the system calls forum_get_completion_state().
- The forum checks its own rules, including the number of posts and anything else that’s enabled. It returns true if these rules are met and false if they’re not.
- Combining this data, the system decides whether to update the completion state. If an update is needed, it makes the change in the database.
Activity UI (course page)
The user interface for students on the course view page needs to allow for displaying progress to students and, where completion is set to manual, allowing students to tick their own progress boxes.
I have based this suggested interface on experience here at the OU. The interface will be implemented via changes to print_section and course view.php.
- Completion displays alongside each activity for which completion is enabled, to the right of the section. (This conveniently separates it from the functional information at the left, and means that all the progress markers line up with each other.)
- Automatic completion displays as a tick or cross icon, by default coloured green and red (accessible colours will be chosen), or some kind of faint outline if something isn’t completed yet. The cross icon is used if completion state is 1.
- Manual completion displays using two more icons (‘manual tick’ and ‘manual blank’). Possible icons would be the same tick with a heavy dotted box around it, and an empty dotted box. The title of the icon is an interface clue to the user e.g. ‘Click to mark this activity completed’.When AJAX is not enabled, the manual icons link to a URL that toggles the completion value then redirects straight back to the course page.When AJAX is enabled, the manual icons use YUI to adjust the completion value without reloading the page. In this case some kind of animation – for example, the word ‘Saved’ appearing next to the icon for a second before fading away – will be used to indicate to users that their change has taken effect.
- If completion is not enabled for an activity (or for the course, site, etc) then the print_section display is the same as at present.
- When editing is turned on, completion information always displays as ticked regardless of the user’s actual completion setting. This makes it easy to see that completion is enabled for that activity.
I will get a graphic designer to look at the icons to use. To reiterate, there are six icons:
- automatic completion, not completed yet (above, not actually shown on its own, but would be a faint grey dotted box)
- automatic completion, completed (above, slightly grey tick, with faint grey dotted surround)
- automatic completion, pass (not shown, e.g. could be a green tick)
- automatic completion, fail (not shown, e.g. could be a red cross)
- manual completion, not completed (heavy black dotted outline)
- manual completion, completed (heavy black dotted outline with black tick)
It may need some work to make the manual ones look clickable and the automatic ones look not clickable, but not irrelevant either. For example we might have to resort to crappy 3D button-style shading on the manual ones. This is what I've done (badly) in the initial version of the icons which I have made.
Configuration UI (activity settings page)
Each activity’s completion settings can be configured on the standard activity settings page. These settings only appear if completion is enabled for the course and site.
The interface will be implemented via a change to the standard_coursemodule_elements function and a new optional form member function completion_add_rules(), as mentioned above, which is called (from within standard_coursemodule_elements) to add the activity-specific form elements.
We also need to determine whether the activity supports grades. This will be determined via the new module_supports() function. (Note that there are existing functions for finding out whether a module instance has a grade, but not for finding out whether a module supports grades if it hasn't been created yet.)
((TODO: Diagram needs redoing))
- A dropdown allows choice of the three completion options – none, manual, automatic. (All three are shown in the diagrams below.) If the module does not support its own completion conditions, and does not support grades, then the ‘automatic’ option will not appear.
- A ‘view’ checkbox only appears if the module supports view tracking. If completion is not set to automatic, it will be greyed out. It allows you to mark something complete as soon as the user goes there once.
- A 'require grade' checkbox only appears if the module supports grades. If completion is not set to automatic, it will be greyed out.
- At this point we could have a dropdown selector to choose which grade item to use if there is more than one. However, at least for the first release, I am not providing a user interface for that feature.
- Module-specific settings, if any, are included. These are also greyed out if completion is not set to automatic. The module can add any number of settings. It is responsible for storing the data from these as part of its normal form processing.
- An expected completion date (default disabled) is given. This can be enabled for manual or automatic completion. It has no practical effect but displays on the progress screen. The intention is that those who design a course can set these dates at key points in the course. During the course, teachers can look at the progress report and use the dates as a guideline to check whether students are falling behind. [At a later date it might be possible to do other things with this data, such as export a list of 'late' students to an external system.]
- If anybody already has stored completion state for this activity, completion settings will be locked: they appear, but read-only. A button allows you to unlock the settings (making those fields editable again); after you do that and save the form, existing completion data is wiped and recalculated against the new conditions. A warning by the button explains that changing completion conditions after students complete things is not a good idea.
Progress tracking UI
Teachers wishing to track student progress can do so via the admin block. The existing course reports page will include a link to view student progress if the user has viewprogress capability.
The resulting page shows a summary of progress either for a particular group, or for all students in the course, according to the normal rules for group selection. It may include a standard group dropdown too.
- Progress is shown in a table. Students (everyone with a role in progresstrackedroles) are displayed down the left of the table and for activities that have completion enabled, the activity names [with expected completion dates, if set] are displayed across the top. Students can be sorted by first name or last name. The student names link to profiles and activity names link to the activities.
- The cells in this grid show progress indicators using the same icons as used on the course view page, although these icons are not clickable in the report. For each cell, the title, which you can see by hovering over it, indicates the state of the cell and the time modified (‘Completed 12/9/08 13:47’) as well as the student's name and the activity name (in case you are scrolling around a table that doesn't fit on-screen).
- A link at the bottom allows this table to be downloaded in CSV format. The downloaded version contains the same data, using two columns (‘state’ and ‘date’) for each activity.
Performance
Course view
When completion is enabled for a course, the course view page needs to obtain completion information. This will be cached in session and retrieved efficiently (hopefully 1 query) the first time.
Module pages
There is no performance impact when using modules that do not support completion, or where completion is disabled.
When you take an action that potentially involves completion (e.g. if you make a forum post to a forum that has enabled automatic completion when you reach N posts) the same completion state cache is used to read the current state of the data, so this should need no queries (you probably already saw the front page).
If your action could potentially change that completion state (e.g. you have not already completed the activity and you just made an additional forum post) there will be an additional cost at that time, depending on the activity – in this case, the forum will do a query to find out how many posts you've made. Because these actions occur relatively rarely, this should not cause a serious problem. (Once you have completed the activity, making another post will not incur the performance penalty.)
View-related completion tracking, the part most potentially problematic, will behave similarly: the first time you view something that has a 'viewed' requirement, it will make extra queries as it marks it viewed (or, if you viewed it in a previous session, loads up that information). After that the information will be cached in your session.
Backup and restore
- When users are included in backup, course backup will include the contents of the _course_modules_completion table.
- Course and course-modules backup will be modified to include the new fields in those tables.
Conditional availability
Conditional options
There is no specific option to enable this part of the feature (?). The parts which depend on the completion system are enabled using the completion flag.
Available conditions
You can place conditions on any activity. Conditions are always combined with Boolean AND, i.e. all conditions must be met before the activity becomes available. Unlike completion, conditions are not module-dependent. There are two types of condition:
- Conditional on date. You can have both of these conditions if required.
- On or after date – activity becomes available on given date.
- Before date – activity becomes unavailable on given date.
- Conditional on other activities. You can have as many of these conditions as desired.
- Activity must be completed – any kind of completion will do.
- Activity must be completed and passed – completion must have been graded and displayed with a pass mark (tick icon).
- Activity must be graded at least/at most N.
Database
- _course_modules
- New field availablefrom, unsigned int (10) not null default 0.0 = Not conditional on date.* = Time (seconds since epoch) after which activity becomes available.
- New field availableuntil, unsigned int(10) not null default 0.0 = Not conditional on date.* = Time (seconds since epoch) after which activity becomes unavailable.
- New field showavailability, unsigned int (1) not null default 0.0 = Activity does not appear at all if conditions are not met.1 = If conditions are not met, activity appears but greyed out (‘hidden’ style) with no link and a short explanation of when it will be available.
- New table _course_modules_avail(able?) which stores any per-module conditions.
- id.
- coursemoduleid [index].ID of the module that is being restricted.
- cmsourceid.ID of module that the restriction is based on.
- requiredcompletion, unsigned int(1) not null default 0.0 = no required completion.1 = required completed.2 = required completed and passed.3 = required completed and failed.
- gradesign, varchar(2).NULL = no required grade.‘<’, ‘<=’, ‘>’, ‘>=’ = requirement for grade.
- requiredgrade, number(10,5 decimals).Grade boundary used together with the above sign. May be null.
API
Two new functions:
- availability_is_available($cm)Returns true if the module is available to students (it is visible, plus availability conditions, if any, are met). Does not include course access conditions, which it assumes have already been checked.This is a slot-in replacement where code checks for $cm->visible at key points such as in require_login.
- availability_get_display_details($cm)Obtains information about the activity’s availability which is required in order to display (or not display) a link to the activity. Returns an object with the following fields:->available – If true, activity is available; users should be allowed to access it / get links to it.->show – If true, activity should be displayed (even to users who do not have viewhiddenactivities)->info – Informational string. Blank if the activity is available.
Other changes:
- For performance reasons we need to cache the conditions in _course_modules_available. Best option is to use existing get_fast_modinfo infrastructure. This should not be hard. The above two functions will use this cache.
Configuration UI (activity settings page)
The configuration UI will be implemented as part of standard_coursemodule_elements in the module forms. The existing ‘visible to students’ option (not changed in database/code) is moved within this UI.
This UI will appear even if completion is not enabled, but the parts related to completion will not show. So if completion is not enabled you will still be able to set available dates if you like, and the interface will remain consistent. The diagram below shows, first, the version that appears with completion not enabled, and then the one you get with completion enabled.
((There should be a diagram here, not sure it will show in the wiki version))
[[Image:]]
- The actual ‘available from’ options should include time as well as date. ‘Available from’ should default to midnight tomorrow; ‘Available until’ should default to 23:59 today. (I got bored laying out combo boxes.)
- ‘Information display’ controls whether informational text is displayed to students when an activity is not available. (See below.) The default is not to show information.
- The list of other activities which might have conditions includes only those other activities on the course which either have completion information, or a grade. Anything which doesn’t have completion information or a grade is omitted.
- Only one condition is permitted per other activity. This isn’t a restriction of the back-end, it just makes the UI simpler.
- The condition type dropdown by each activity is adjusted dynamically to include only options that are valid for that activity:
- ‘Completed’ appears only if completion is enabled for the activity.
- ‘Completed with pass’ and ‘Completed with fail’ (which I missed off the diagram by accident) appear only if completion is enabled for the activity, and set to a grade item, and the grade item contains a pass mark.
- The grade conditions appear only if the activity has a grade item.
- The grade box is a text-entry field. Users type in the floating-point number version of the required grade.
Activity UI (course page)
(This will be accomplished via code changes to print_section. Logic is basically the same as for the current visible flag.)
For available activities, the display obviously does not change. Unavailable activities will be displayed as follows:
- If the current user has viewhiddenactivities:
- The activity displays using the CSS style for hidden activities.
- The informational message as to why the activity isn’t available is displayed (even if showinfo is not set).
- If the current user does not have viewhiddenactivities:
- If showavailability is not set, or if the activity is actually hidden (visibility 0), the activity does not display at all.
- If showavailability is set and the activity isn’t hidden but is unavailable for some other reason, the name of the activity displays using the CSS style for hidden activities, but does not include an actual link to the activity. The informational message as to why the activity isn’t available is displayed.
Here are some examples of hidden activities with informational text:Assignment resources Available from 6 Oct 2008Assignment resources Available when Unit 1 Test grade is > 90Assignment resources Available when Tutor group forum is marked complete (+ other requirements)When there are multiple conditions, only one is shown. Date is considered first; the order after that is arbitrary.
Behaviour is the same when editing is turned on except that the ‘availability’ string moves to the line below so as not to clash with all those icons.
Performance
This adds a single quick database query to the course view page for courses which have enabled conditional activities / completion.
All other information is cached in modinfo, so does not have a performance penalty, save one problematic issue: the feature that allows arbitrary grade information to be considered. If you use pass/fail information, that’s fine, it’s there already in the completion data. But if you use a specific grade [and for example it could be different values for different activities] then the actual grade for the item needs to be retrieved on course view.
I don’t believe this will pose a massive performance issue as it only applies when modules are used as source for this kind of information. We should review this once it’s developed and, if necessary, optimise performance then. There are various caching approaches we could use.
Module delete
If you try to delete a module, it will check to see if that module is referenced by any other module as a condition. If that’s the case, you will not be allowed to delete it. An error message will include a link to the module edit page for the other module (so you can go there and delete the condition if you like).
Backup and restore
- The new _course_modules_available table will be backed up and restored.
- Partial restore needs to be handled. If your backup includes module A but not module B, and module A had a condition on B, then that condition will not be restored.
- Backup will also be modified to include the fields added to _course_modules.
- If you restore a course with a startdateoffset, it will offset the dates from the new _course_modules date fields.
Module supported features
As part of the completion system, I needed a way for modules to indicate support of certain features, so I propose a generic one which I have implemented:
- A module API function module_supports($feature) which returns false if the feature is not available, and true (or an object with more information, if needed for specific features) if it is.
- A standard API function module_supports($modulename,$feature) which works as follows:
- If the $modulename_supports_feature function exists, it calls that function and returns the result.
- Otherwise it returns false – or, if features are added that correspond to ‘legacy’ ones that we can find out another way (e.g. by looking to see if a function exists) then this can be done.
- A set of FEATURE_xx constants. For this code, the following are necessary:
- FEATURE_GRADE_HAS_GRADE
- FEATURE_COMPLETION_TRACKS_VIEWS
- FEATURE_COMPLETION_HAS_RULES
- Other feature constants could be added as desired, e.g. FEATURE_CRON, etc. My initial implementation will include only the 'new' ones needed for this work.
Note that this implementation would not be appropriate if modules were changed to be fully object-oriented. However I don't expect that to happen in Moodle 2 so this is probably OK.