Development:Conditional activities: Difference between revisions

From MoodleDocs
 
(15 intermediate revisions by 6 users not shown)
Line 1: Line 1:
This is a developer's page for Moodle Version 2.0, describing an evolving specification.  UNDER CONSTRUCTION!
{{Moodle_2.0}}


Conditional activities allow the course editor to hide certain activities until conditions on other activities have been met. 
= Design document =


For example, a student will not see Assignment B until they have scored 80% or higher on Quiz A.  
(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.)


==Objectives==
See MDL-15497 for tasks and tracking.


# We want to know when activities are finished (for each user independently)
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.
# We want to have this calculated automatically, but also manually if required.
# We want other some activities to be hidden until other activities are done.
# We want to "chain" these things into learning paths.
# We want the course page to remain fast.
# We want conditional activities to be optional.


[[User:sam marshall|sam marshall]] For us and no doubt other places, the 'activity completion' part of the system is still useful even if we are not using conditional activities for a course. We would then want a reporting interface so that tutors can see which tracked activities their students have/haven't completed. (And for course staff, obviously they would be able to see all students on the course in the same manner.)
== 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.


==Overview==
This is divided into two related, but separate, chunks of work.


There are two main approaches to this.  For the discussion below let's use A to mean a source activity, and B and C to mean two activities that are only available when A is done.
=== Completion tracking ===
Make the system store whether or not an activity has been ‘completed’.  


Approach 1: The one used by activity locking is to place the UI to choose the conditions in B, so that it specifies the passing grades etc that are needed for A so that B is unlocked.  This has advantages in that B can specify a different passing grade that C (both on the same A).
This may be according to an activity-specific definition of completion, or because the student has ticked a box saying they’ve finished it.


Approach 2: This places the logic in A, so that it defines when it is "done" any way it likes and B can just say "I'm available when A is done".  The advantages here are that A can define "done" in any way it likes, and the configuration can be more subtle if the module wants 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’.


The approach described below actually combines BOTH these approaches so it should please everyone and allow the maximum flexibility.
It should be possible for teachers to access progress information for their students, so that they can see if anyone is falling behind.


==Interfaces==  
=== Conditional availability ===
Allow or prevent access to an activity depending on various conditions.


===Site settings===
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.


Admins can turn Conditional Activities on/off for the whole site.
=== Development process ===
I will do this work here. It is possible that time constraints might mean I only do the first part (completion tracking).


===Course settings===
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).


Teachers can choose between three states for a course:
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.
# Conditional Activities off
# Conditional Activities Manual
# Conditional Activities Auto


===Course page===
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.


For teachers
== Completion tracking ==
* Each activity will have an icon indicating the status, and clicking on it takes you to the activity settings (see below).  These are also available as a tab from the main activity pages.
=== Completion options ===
The completion system can be enabled or disabled at site, course, and activity level.


For students
* At site level, the new admin variable $CFG->enablecompletion (defaults to 1?).
* Colour icons (checkboxes) in red/orange/green down the side of the course format indicate the status of each activity
* At course level, a new mdl_course field enablecompletion (defaults to 1).
* In manual mode, these can be clicked on to toggle the status as required (so that students can manually keep track of what they've done).
* 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.
* In auto mode, these icons are fixed


[[User:sam marshall|sam marshall]] Be very careful with colours. You mustn't use colour as only way of displaying information (accessibility). I'd suggest something like: For manual mode, use straightforward checkbox as above; For auto mode, use an icon as described but make these look different as well as different colour (I'd suggest grey crosshatching for unavailable, white (hollow w/black outline) for available but not done, green tick inside box for done-pass, red cross inside box for done-fail) and of course include alt text
This table illustrates the effect of these options. (‘enablecompletion’ is abbreviated to ‘ec’.)


[[User:sam marshall|sam marshall]] 'Manual' and 'Auto' modes maybe needs rethinking. I think this should be actually be a choice of 'disable system' (why? well, anyway), 'enable system', and 'enable system plus student progress'. These are equiv to off, auto, and auto+manual. The reason for this is that if you specify conditions for something you always want it to be 'auto' obviously. But, anything you didn't specify conditions for, it could be 'manual' (i.e. you want students to track progress on some things that are not trackable automatically, e.g. 'go and read this web link' (a link) or 'go and read the book we sent you' (a label)


[[User:sam marshall|sam marshall]] If this approach is adopted (or anyway for standard manual), it needs a way to turn off progress support per-activity, this could be in course_modules or whatever. For example you don't want to include a 'progress' box on something like a generic course forum that is available for the life of the course, or a course resources page that's similar, or a page about how to contact student support. We do this because in editing mode, our checkboxes include a tiny little eye icon next to them so you can hide them where they aren't needed. Maybe also appropriate to set defaults i.e. labels default to not having progress.
{| class="prettytable"
| '''Location'''
| '''Feature'''
| '''Appears if'''


[[User:sam marshall|sam marshall]] At the OU we use an option that controls who sees the checkbox. Remember course:participate? YES IT'S THAT AGAIN. Not that it is really really desperately needed or anything. Ahem. But anyhow, we have a specific permission for who the progress system applies to, and this is checked with doanything=false. You might need something similar.
|-
| Admin settings
| On-off toggle for $CFG->ec
| –


===Activity settings===
|-
| Course settings
| On-off toggle for course ec
| $CFG->ec


When the teacher is editing the activity settings for each activity, they see two parts to the page:
|-
| Activity settings
| Off/manual/automatic option for course-module completion
| $CFG->ec && course ec


====This activity will be available when ...====
|-
| Course view
| Completion display/controls against activity
| $CFG->ec && course ec && completion


The UI here is standard for all modules. (Settings are stored in the '''course_modules_avail''' table.)  It shows all the other activities in the course, and beside each of them are menus to choose from:
|-
* Grade >= X  (<, <=, >= and >)
| Admin block
* Viewed
| Link to progress report
* Completed (as defined by that activity)
| $CFG->ec && course ec && user has permission


[[User:sam marshall|sam marshall]] Should also include date as a condition. Would be stored in course_modules_avail
|}
=== Completion states and conditions ===
Completion state is stored per-user for every activity. There are four states:


[[User:sam marshall|sam marshall]] Maybe consider also an option for whether the activity is visible before it is available, greyed out with a 'This activity will be available when...' note, or not displayed at all.
* <nowiki>Not completed [default – not stored in database]</nowiki>
* Completed (pass/fail unspecified)
* Completed, passed
* Completed, failed


====This activity will be completed when ...====
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:


This UI shows optional settings for this activity to define when it thinks it is finished. (Settings are stored in '''course_modules_done''' table):
* Grade visible, ‘grade to pass’ set: ‘completed, passed’ and ‘completed, failed’ states will be used.
* Grade >= X  (<, <=, >= and >)
* ‘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.
* Viewed
* Something else (interface defined by module)


==Tables==
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.


===course_modules_completion===
==== Standard conditions ====
This table records the status of each user completing each activity module.  It represents current state and is used to make the display of course pages very fast.  It is updated whenever grades or modules change etc.
There are two standard conditions which do not require (much) module-specific behaviour.


* id
* Graded – module has assigned grade for student.
* courseid  - just here for speed
** 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.)
* cmid  - FK to course_modules
** This condition is implemented by a hook in gradebook that runs at the point where a grade is set.
* userid
* Viewed – student has viewed module.
* status - hide / not done / in progress / done fail / done pass
** 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).
* timemodified


==== Custom conditions ====
Modules can support arbitrary custom conditions (with their own form components to configure these, and their own data storage to track them).


===course_completion===
Example conditions might be:
This table records when whole courses are completed.


[[User:sam marshall|sam marshall]] How is this defined? I think it probably needs a way to specify conditions for the course.
* 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.


* id
It is up to the module to determine when a condition has been met and update the user’s completion.
* userid
* courseid
* status


===course_modules_avail===
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.
Records settings for availability
* id
* cmid  - the activity that is defining the condition
* cmsourceid - the activity we are checking
* gradesign  - <, >, <=, => etc
* gradecutoff
* views - boolean
* modulespecific - boolean


===course_modules_done===
==== Combining conditions ====
Records settings for whether something is done
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.
* id
* cmid
* gradesign  - <, >, <=, => etc
* gradecutoff
* views - boolean


==Process==
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.


Coming soon
=== 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.


==Issues to think about==
=== Database ===
(''Prefix is shown as _. Constants are defined for all values here.'')


* How do we cope with circular references?
* _course
* We should remove conditions when activities are deleted - how does that affect things downstream?
** +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/N<sup>th</sup> 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<nowiki>* = time (seconds since epoch) by which activity is expected to be completed. </nowiki>
* New table _course_modules_completion which stores completion state for a user on each activity.
** id.
** coursemoduleid<nowiki> [index].</nowiki>
** userid<nowiki> [index]</nowiki>.
** 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<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 ===
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 completion_add_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.
* <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.
=== 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<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).
# 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.<nowiki>* = Time (seconds since epoch</nowiki>) after which activity becomes available.
** New field availableuntil, unsigned int(10) not null default 0.0 = Not conditional on date.<nowiki>* = Time (seconds since epoch) after which activity becomes unavailable.</nowiki>
** 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<nowiki> [index]</nowiki>.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.<nowiki>‘<’, ‘<=</nowiki>’, ‘>’, ‘>=’ = 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<nowiki>, 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.</nowiki>
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.


==See also==
==See also==
*Take a look at the [http://moodle.org/mod/forum/view.php?f=678 Conditional activities forum] at [http://moodle.org http://moodle.org].
*[[Activity_Locking]], a MoodleDoc page with table and descriptions of different conditional activity modules
*[[Score Lock]] a MoodleDoc page for another conditional activity module for 1.6
*[http://moodle.org/mod/forum/discuss.php?d=35488 forum discussion about Stuart Mayor's Conditional Activities], including Moodle 1.6 version
*[http://moodle.org/mod/forum/discuss.php?d=36697 Conditional activities at CICEI], running demo included as student, teacher and designer.
*[[Adding/editing_a_lesson#Dependent_on]] MoodleDoc page . The lesson activity settings in V 1.6 has a specialized dependency setting. Entering the lesson can be made dependent on the % (lesson questions) correct, time spent or completion of one other specific lesson.


*Tracker reference(s) for conditional development _____________
* [[Development:Conditional activities_Adding module support]]
* [[Conditional activities]]


[[Category:Developer|Conditional activities]]
[[Category:Conditional activities]]
[[Category:Completion]]

Latest revision as of 10:59, 5 May 2010

Template: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 completion_add_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.

  1. 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.
  2. 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).
  3. 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:

  1. 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.
  2. 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.

See also