Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Courses "Elements" Epic #522

Open
thomasplevy opened this issue May 1, 2018 · 20 comments

Comments

@thomasplevy
Copy link
Member

commented May 1, 2018

  • Allow nested sections by making the course function like a section
  • Sections can belong to other sections
  • Add "Landing Page" elements (exist only within a course)
  • API for custom course elements
  • Anything on site could be an element (blog posts, page, etc...) these can be accessible outside the course as well
  • element conditions ( display to only enrolled vs unenrolled or only to memberships or only to access plans or any combination thereof)
@thomasplevy thomasplevy added this to the Future milestone May 1, 2018
@thomasplevy thomasplevy changed the title Courses "Elements" Courses "Elements" Epic May 1, 2018
@actual-saurabh

This comment has been minimized.

Copy link
Contributor

commented May 6, 2018

I have had more time to consider this and now have more detailed and specific thoughts:

Course = Learning Experience

I feel I can explain things a little better using a certain vocabulary which can be changed to make more sense (say in a customer facing context). The first change I make is instead of calling something a Course, I'd call it a Learning Experience. This is more in line with the industry standard xAPI specifications.

Calling it a Learning Experience also breaks it out of the constraints of textbook like rigid Course experiences. This term then can begin to describe user guides, workbooks, conferences, offline courses, self-support contexts like diagnosis, repair, decision making wizards, guided tours, onboarding experiences, etc.

Whether called a Course of a Learning Experience, LifterLMS could then potentially power really interactive support wizards, need based learning and customer/user on-boarding wizards and workbook or retrospective record like accompaniments to conferences, classroom learning, etc apart from continuing to power traditional courses.

@actual-saurabh

This comment has been minimized.

Copy link
Contributor

commented May 6, 2018

Sectioning

A Learning Experience has the same mental model as a Journey made up of Steps. Steps can be grouped and a group of steps can be sectioned into smaller groups of steps. So, these groups can still be called Sections or Modules and are similar to the mental models of a leg of a tour, a stage of a journey.

In this sense, the whole Journey/ Learning Experience/ Course is also a Super-section or a top-level section that's sectioned further.

Also, like real life, a Journey or its Sections can have multiple laps (repeatable attempts).

@actual-saurabh

This comment has been minimized.

Copy link
Contributor

commented May 6, 2018

Steps

Each step in the journey is also a task to be tracked, completed and reported.

Each step of the journey is a separate object from the content involved in the step. A step is not responsible for maintaining the content that the student encounters when on this step.

Rather than being the content, a step is only aware of its relationship with a piece of content. This allows us much more flexibility:

  • A piece of content can be re-used across many steps in the same or multiple sections (where section also means a course)
  • A step could potentially load different variations of the content based on different factors(for example for different access plans, memberships, etc or as simple as enrolled vs unenrolled students)
  • CRUD operations on a piece of content can stay independent of CRUD operations on a step. So deleting a lesson would not have huge ramifications on the course structure like it does now.
  • A step also becomes free to associate with any kind of content outside the builtin content types. So, a step could potentially be
    • an event post type of an event manager plugin (attending it completes the step),
    • a WooCommerce product (buying which completes the step),
    • a blogpost,
    • a static WordPress page,
    • a recipe powered by a recipe plugin,
    • an external URL or activity which tracks completion and notifies LifterLMS of the step completion through an API. For example,
      • a successfully merged Pull Request on Github
      • a successful build on a CI
      • successful creation of a profile with necessary fields filled out
      • successfully publishing a piece of content on a WordPress blog or another platform, etc
      • successful creation of a Facebook page
      • attendance and completion of an online Zoom meeting, etc)
    • Offline/manual tracking and completion by the instructor where no content could be involved.
@actual-saurabh

This comment has been minimized.

Copy link
Contributor

commented May 6, 2018

Steps = Tasks

Each step also behaves exactly like task with stati and attempts.

An attempt is just an iteration of the task over all its possible state changes. A task could allow a single attempt or multiple attempts. The ability to re-attempt tasks can be dynamic (manual by instructor, based on the score at completion, etc).

Each attempt can have a score that can be recorded at the time of completion.

An activity describes a change in the state (state transition) of a task for each attempt:

  1. Unregistered
  2. Registered (but not initialized)
  3. Initialized (started the task, play)
  4. Suspended (paused, took a break)
  5. Resumed (unpaused, play)
  6. Completed (task over without a success/failure indication)
  7. Passed (special completion indicating success)
  8. Failed (special completion indicating failure)

There can be other things that can happen to a task when it interacts with the student and can be described using verbs in xAPI:

<?php

return $verbs = array(
	0 => array(
		'name' => 'registered', // task status changes from unregistered to registered
		'verb' => 'http://adlnet.gov/expapi/verbs/registered',
	),
	1 => array(
		'name' => 'initialized', // status changes from registered but un-initialized (event not started yet, lesson content not opened yet, quiz question not viewed yet, video loaded but not viewed) to initialized (event started, lesson viewed, quiz question opened, video started playing)
		'verb' => 'http://adlnet.gov/expapi/verbs/initialized',
	),
	2 =>array(
		'name' => 'requested-attention', // when student pauses the task and asks the instructor a question or student failed in a task and can't go further without instructor intervention
		'verb' => 'http://id.tincanapi.com/verb/requested-attention',
	),
	3 =>array(
		'name' => 'suspended', // when student leaves a lesson without scrolling to the bottom, without viewing a certain percentage of a video or goes on a `break` (breaks are useful things and I'll discuss them shortly)
		'verb' => 'http://adlnet.gov/expapi/verbs/suspended',
	),
	3 => array(
		'name' => 'resumed', // when student comes back to play the unfinished video, etc. Except for the fact that there was a prior suspension involved, this state is the same as initialized 
		'verb' => 'http://adlnet.gov/expapi/verbs/resumed',
	),
	4 => array(
		'name' => 'completed', // when the task is completed, over
		'verb' => 'http://adlnet.gov/expapi/verbs/completed',
	),
	// question & task specific
	5 => array(
		'name' => 'attempted', // this can be used to record multiple attempts or laps for a task
		'verb' => 'http://adlnet.gov/expapi/verbs/attempted',
	),
	// question & task specific
	6 => array(
		'name' => 'answered', // similar to attempted but indicates that there was a response from the student involved
		'verb' => 'http://adlnet.gov/expapi/verbs/answered',
	),
	7 => array(
		'name' => 'passed', // records a specific type of completion- success
		'verb' => 'http://adlnet.gov/expapi/verbs/passed',
	),
	8 => array(
		'name' => 'failed', // records failure
		'verb' => 'http://adlnet.gov/expapi/verbs/failed',
	),
);

Also see: https://github.com/adlnet-archive/xAPIVerbs/blob/master/verbs.js , http://xapi.vocab.pub/describe/?url=https://w3id.org/xapi/adl for a list.

See: https://registry.tincanapi.com/#home/verbs for the full list of verbs including those that can be used to describe tasks for instructors and other roles.

So, tasks can be defined and assigned to either a student, instructor or any other role (for example, observer, course manager [administrative assistant], etc).

And tasks can be observed by observers (subscribers) (supervisor at work, parent in a school, etc) with various levels of permissions and capabilities on the task (like reserving the ability to mark a task complete can stay with the instructor even if student completes everything involved).

@actual-saurabh

This comment has been minimized.

Copy link
Contributor

commented May 6, 2018

Tasks as Composite Objects

Tasks can be composite, which means that a task can be made up of other tasks:

  • This way, a whole quiz can be described as a composite task which gets completed only when all the sub-tasks (questions) are completed.
  • An assignment can be described as a composite task which gets completed only when all the sub-tasks (assignment tasks) are completed.
  • A lesson can be described as a composite task which gets completed only when all the sub-tasks (passing a quiz with a certain percentage, filling up a form, manually check a reading list made up of URLs, finish playing a video to 80%, etc)
  • A section can be described as a composite task which gets completed when all the steps involved are completed (steps can be lessons, assignments, quizzes, events, etc like described above).
  • A learning experience/ course can be described as a composite task which gets completed when all the steps and sections involved in it are completed.

Tasks Relationships

In addition to being a composition of sub-tasks, a task can have other relationships with other tasks. Another task can become a pre-requisite (requirement) for a task or become dependant (where other tasks becomes a requirement) on other tasks.

Sequential Completion

Completion of a task may involve completing sub-tasks in a particular sequence or completing pre-requisites in a particular sequence.

What this effectively means is that if a student completes tasks in a particular sequence, a different task is completed that when they complete it in another sequence. I haven't gone into sequencing much but BadgeOS does this well.

We could look at some Task Management & Project Management systems for inspiration on how to model tasks (or steps).

@actual-saurabh

This comment has been minimized.

Copy link
Contributor

commented May 6, 2018

Milestones = Task state transition log

Everytime a task's status changes, these changes can be logged along with a timestamp in an activity log in the database.

This activity log can use the exact model (structure) of an xAPI statement:

  1. Actor (student, instructor, observer)
  2. Verb (describing the state transition and described in #522 (comment)
  3. Object (the task itself or a particular attempt for a task which would be a reference to another log entry with the verb attempted where the object is the task itself)
  4. Context (details of the access plan, membership, instructor and any other parameters)
  5. Result (to store the score or reference to another activity with the passed or failed verb)

This way, it behaves like a builtin LRS. This effectively means opening up possibilities of integrating with other xAPI compliant systems including third-party LRSes, project management systems, etc. See: https://xapi.com/sharing-statements/

This is a model extremely similar to what is understood as an activity update in a social network which means that the LMS can integrate easily with social networking plugins like BuddyPress https://buddypress.org/wp-content/uploads/15/2013/11/bp_db_schema_v1.0.png
screen shot 2018-05-06 at 1 46 05 pm

or PeepSo (https://plugins.trac.wordpress.org/browser/peepso-core/trunk/activity/classes/activity.php, https://plugins.trac.wordpress.org/browser/peepso-core/trunk/activity/activitystream.php) or any third party social networks (FB, Twitter, etc).

Finally, since all the progress and interactions are tracked and stored with xAPI compatible statements, you could use https://github.com/adlnet/Intro-to-xAPI-Data-Visualization/tree/master/reporting to create highly detailed and granular reporting that the user can set up and customise freely.

@actual-saurabh

This comment has been minimized.

Copy link
Contributor

commented May 6, 2018

State transition triggers

Each task state transition can trigger granular hooks that describe transition-from, transition-from-and-to and transition-to:

<?php


// announce generic task state transition for all task types
do_action( "llms_transition", $new_status, $old_status, $step_type, $step );

// generic state transition for specific task type
do_action( "llms_transition/{$step_type}", $new_status, $old_status, $step );

// state transition specific to the final state for all tasks
do_action( "llms_transition/to/{$new_status}/", $old_status, $step_type, $step );

// specific to the final state for a specific task type
do_action( "llms_transition/{$step_type}/to/{$new_status}/", $old_status, $step );

// if this is a transition from an earlier state
if ( ! empty( $old_status ) ) {

    // from an initial state for all tasks
    do_action( "llms_transition/from/{$old_status}", $new_status, $step_type, $step);

    // from an initial state for a specific type of task
    do_action( "llms_transition/{$step_type}/from/{$old_status}", $step );

    // between a specific initial state and specific final state for all tasks
    do_action( "llms_transition/from/{$old_status}/to/{$new_status}", $step_type, $step );

    // between a specific initial state and a specific final state for a specific type of task
    do_action( "llms_transition/{$step_type}/from/{$old_status}/to/{$new_status}", $step );
 }

Using these, you could set up really specific triggers to drive engagements of various types.

The step type should be a controlled vocabulary similar to post_types, taxonomies and post_status that can be registered and unregistered. Unlike WordPress's controlled vocabulary, these can be hierarchical and have sub-types. So a step type like question which can have a sub-type called mcq and so on.

Step Types

  • membership
  • access-plan (there can be an access-plan at any step that corresponds to registered verb)
  • course
  • section
  • lesson
  • quiz (so quiz can reside outside a lesson, at the level of a section or even the course, itself)
  • question (so questions can be outside a quiz and into the lesson content)
  • assignment
  • task (so tasks can be outside an assignment and into the lesson content like a reading list, checklist)
  • achievement (?)
  • course-page
  • decision-point
  • WordPress post type
  • external resource
@actual-saurabh

This comment has been minimized.

Copy link
Contributor

commented May 6, 2018

Task (step) Status Transition & Achievements

Using the granular hooks, it'd be easy to pick up any kind of transition to trigger an achievement or engagement including notifications, certificates, badges and third-party API calls.

We could even build an interface that more advanced users could use to set up really granular achievements or notifications.

Just like Steps or Tasks described earlier, these engagements can also be decoupled from the content of such engagements allowing for the kind of flexibility that users have wanted for quite some time.

@actual-saurabh

This comment has been minimized.

Copy link
Contributor

commented May 6, 2018

Content Variations

Similar to WordPress's builtin revision functionality or WooCommerce's product variations, we could include support for content variations.

These variations would work similar to how Meta Queries work in WordPress with all the properties that describe the state of the Step object as parameters and their values forming the queries.

There can be a complex, nested AND & OR relationship between each condition. See: https://codex.wordpress.org/Class_Reference/WP_Meta_Query#Initializing_WP_Meta_Query

In addition, each condition can have a comparison property very similar to WP's meta query, viz =, !=, >, >=, <, <=, LIKE, NOT LIKE, IN, NOT IN, BETWEEN, NOT BETWEEN, EXISTS, NOT EXISTS, REGEXP, NOT REGEXP and RLIKE.

So, using this architecture, as an example, when two students who sign up using two different access plans land at the start of a section, they may experience different variations of the section. So, I can have sections exclusively for some access plans, memberships, etc.

Similarly, the whole course may just have 2 or 3 variations (which probably just have the same sections organised in a different manner or have additional special content that's available only to a particular access plan or have different drip settings for different students, etc).

The same principle of content-variations could be used for notifications, certificates, badges, points or other milestone-based triggers. So, a special member could get a special certificate with a different design and a regular member may get another. Completing a course for free may not trigger a certificate at all, as another example.

The possible flexibility is endless.

@actual-saurabh

This comment has been minimized.

Copy link
Contributor

commented May 6, 2018

Conditional Dynamics & Decision Points

The Step & Section objects defined above behave like a course element and is associated with a content element and its variations. Based on the current context defined by the values of various parameters (student id, membership, access plan, etc), a step or a section can load a different variation of the same content element.

In addition to that, I propose adding another type of element, called decision-point (because I couldn't come up with a better name, for the time being).

Similarities with Steps
Their states and parameters and conditional rules can behave exactly like Steps. So, their is similarity in the Object Model. They can behave like tasks completed and recorded in the background.

Dissimilarities
Unlike steps, decision points don't have associated content and its variations. Instead, they are made up of options which correlate to an actual Step in the experience (maybe even a specific variation) and are only used to manage the control flow.

For example, one may add a decision point after Section 1, where the context can be analysed (including results of quizzes and assignments) and the decision made to land the user on either Section 2 or skip it and land them on Section 3. So, the user who completes Section 1 successfully goes to Section 3 and the user who fails lands on Section 2.

@actual-saurabh

This comment has been minimized.

Copy link
Contributor

commented May 6, 2018

Static Pages

These behave exactly like static WordPress pages but are specific to learning experiences. These can be used to create a landing page for a section (where a section can also be a course).

So in a course, I can add the first step and add a Static Course Page as the content for the step. Next, I create variations of this static page for:

  • Enrolled Student from Access Plan 1.
  • Enrolled Student from Access Plan 2.
  • Unenrolled but logged in user.
  • Unenrolled but user belonging to Membership 1.
  • Unenrolled but belonging to Membership 2.

Similarly, I could create another step and associate a static page only for instructors (skipped for students) or only for a particular access plan (skipped for other access plans) and so on.

Since these (and all other course elements) are just regular WordPress post_types, the content building can be done using any page builder, gutenberg or any other mechanism out there which solves another issue that is faced by a lot of users.

@actual-saurabh

This comment has been minimized.

Copy link
Contributor

commented May 6, 2018

Cascading Functionality and Context Properties
The values for all the parameters (states) and methods (interface) would be inherited from the top-most level (course/ learning experience) and will propagate inside the composite nested tree that the course-structure is.

Each level (section/step) can decide what properties does it recognise and use and what it doesn't care about (scores for example, are of no use in lessons or static pages).

Each level (section/step) can decide whether it will inherit the properties from a higher level or override it because the user specified otherwise.

This way all properties and methods can be propagated and hence functionality can be inherited.

So, if a course can have access plans and can be sold as a product, a section or a step can also have separate access plans and ways to sell them and so on.

@actual-saurabh

This comment has been minimized.

Copy link
Contributor

commented May 6, 2018

Break as a valid Step in Learning Experience

In addition to course elements and decision points, there should be a break type step.

This could be defined explicitly by the course creator so that the students are forced on a break from the course, to accommodate any offline activity (a test, quiz, assignment, examination, etc) they'd like the students to do. This would also allow for more traditional classroom management where you could create summer breaks where further dripping or progress in the course is paused for a duration.

In addition, dynamic breaks can be generated and recorded on the fly, when the student pauses (suspends) a step or a section (even a course). In addition, breaks can have time limits, crossing which could trigger notifications or other engagements just like tasks do (like sending an email to entice a student to come back and complete the course).

With the LRS like reporting, one could use the break data to analyse abandonments and improve the course content and flow.

This along with decision points and content variations can help course-creators perform A/B testing (theoretically) and test out strategies that lead to better course completion rates.

@actual-saurabh

This comment has been minimized.

Copy link
Contributor

commented May 6, 2018

Taxonomy & Terms based Conditionals

Like WooCommerce's variations, any taxonomy can be used like a parameter and its terms as values for the parameter, as described in #522 (comment)

Which means that, for example, if I'm building a course to teach IT related course, my first step could be a form where the user can choose the Operating System & Browser. Using the terms they've chosen, my subsequent Steps (or Sections) can be a specific variation.

So, I'll have different variations of some lessons (or quizzes or even individual questions) for Windows, Mac and Ubuntu. Same way, different variations of a lesson containing a video for Chrome, Firefox or Opera or even different variations of a lesson for Chrome on Windows, Chrome on Mac and Chrome on Ubuntu using the meta query like conditions.

In fact, one could use any property or parameter that behaves like a controlled vocabulary, even if it is not an explicit taxonomy in WordPress for conditionals and variations. Access Plans available for a course, the various instructors that can be available to mentor a student's learning experience, a student's location (for l10n based variations), language (to integrate with multi-lingual plugins), timezones, user role (student, instructor, observer, manager, etc) can all be parameters used to load a variation instead of the default content.

In addition, this correlates well with WooCommerce's product variations and can be used to create varieties of learning experiences that are sold at different costs at different types while still being the same course. This is something that's demanded very often.

@actual-saurabh

This comment has been minimized.

Copy link
Contributor

commented May 6, 2018

Recognising & Tracking other post types

Other than the inbuilt post-types of LifterLMS and WordPress, there should be an option for users to check post types that they'd like LifterLMS to recognise and manage (for restrictions and variations, for instance).

This is in addition to the ability to associate any post type with a step in the Learning Experience.

@actual-saurabh

This comment has been minimized.

Copy link
Contributor

commented May 6, 2018

Conditional content components

This would an extreme level of dynamic content where the variation logic that is applied to a whole post object is applied to a component (page-builder/ gutenberg blocks). Once Gutenberg is in core and stable for a while and page builders start speaking a common language, each block could have variations. This would be just mind-blowing amount of flexibility.

@actual-saurabh

This comment has been minimized.

Copy link
Contributor

commented May 6, 2018

User Roles & Personas

Just like every other object states and interfaces, Users can have different roles at different levels. So, the user who is an instructor in one course could be a student in another and so on.

In addition, most functionality and settings can be organised into a WordPress capability based permission architecture that can be used to define what a user can do and not do on a course, section, lesson or quiz.

This way, you could create many more roles:

Course Manager: maybe can get some reports and notified of payment and abandonment related triggers. Can manage enrollments and unenrollmenst. Cannot grade asignments and quizzes. Cannot alter course structure or content.

Course Observer: can do a bit more and access more reports and notifications but cannot do what instructors or students can do.

Course Subscriber: can only receive notifications and some reports, like parents in a school or employer of an organisation (who sponsors the course and needs to get updates)

Using code or a user role plugin, users could create roles with specific capabilities based on their organisational or training process requirements.

Each role can also take on the Persona of another role and go through the learning experience, if allowed. So, a Course Administrator can take on the persona of a Course Manager and experience the course like a manager and so on.

@actual-saurabh

This comment has been minimized.

Copy link
Contributor

commented May 7, 2018

To get started at the very basics and to solve one of the most-common issues,

  1. Let's start with adding two post types:
    1. course-page/ static-page/ landing-page: I prefer the first because this can be much more than a landing page.
    2. llms-variation: Without exposing this functionality to users, as of now, we can create this in the background.
  2. We take the non-enrolled content from the course and move it into a course-page post.
  3. We take the enrolled content from the course and move it into a llms-variation post and set this post's parent_id to the course-page's post type in 2 above.
  4. Right now, we don't implement the variation architecture anywhere else except for course-pages and only for hard-coded enrolled vs non-enrolled contexts.

This way, we get to test the hell out of this variations business and solve a very common issue that plugins like this are trying to solve: https://wordpress.org/plugins/custom-template-lifterlms/

The landing pages will immediately start working with all page builders out there if users opt for this post type in the page builders' settings (another reason to call this Course Page):

screen shot 2018-05-07 at 7 03 30 pm

There's no need to add the ability to add these post types anywhere else, except right at the start of the course, before the first section so that they function exactly like a landing page.

In terms of UX, this can look exactly like a current Section with Lessons:

screen shot 2018-05-07 at 7 37 41 pm

Later on, we can add possibilities of dragging more landing pages specific to Access Plans, Memberships, etc.

These course-pages that are dragged into the Landing Page section will have an auto-generated title (not editable by course creator) based on a schema that we can come up with that describes the kind of users who'll get to see the landing page.

@actual-saurabh

This comment has been minimized.

Copy link
Contributor

commented May 8, 2018

A Note on Quiz

RIght now, quizzes are pretty rigid in the way they can be created and structured. With a composite step like object, users would be able to section quizzes, create synonymous relationships between questions (where any of a set of questions test the same thing and can be picked randomly in a quiz) using variations and setup result and score type states on sections and groups of questions (for psychometric and psychological test style quizzes & surveys).

This compositing will also allow us to have composite type of questions, like

  1. match columns where each item in the LHS column is an MCQ on its own and all such MCQs (represented by LHS items) have the same options (RHS) http://caacentre.lboro.ac.uk/resources/objective_tests/matchingitems.shtml, https://codepen.io/saurabhshukla/pen/VxyeKB
  2. assertion-reason questions http://caacentre.lboro.ac.uk/resources/objective_tests/assertion.shtml, https://codepen.io/saurabhshukla/pen/qpVMYY
  3. Multiple input questions like hotspot/ sore finger questions: http://caacentre.lboro.ac.uk/resources/objective_tests/othertypes.shtml, https://codepen.io/saurabhshukla/pen/mpqzyb, https://codepen.io/saurabhshukla/pen/ZvaqLx, https://codepen.io/saurabhshukla/pen/qpVQrZ
@actual-saurabh

This comment has been minimized.

Copy link
Contributor

commented Jun 20, 2018

I think the right way to think of and implement personalisation and variations is on the lines of email marketing terminology: tags and segments. I don't understand the distinction very well but course element variations can be tied into tags based on single user actions and segments based on tags, Access Plans, enrollment into other courses/memberships, user role, user-meta, etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.