Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

Adding question types to lesson

From MoodleDocs

Please note that this page deals with a future version of Moodle 2.x.

A regularly discussed topic is that Lesson should use the same question classes as Quiz. This page is geared toward this goal by explaining the different aspects required to complete this project.

Project goals

  • (Primary) Implement the question type classes in Lesson.
  • (Primary) Reduce Moodle's code base. Instead of Lesson having its own question code, it can now use existing code.
  • Simplify Lesson's code. There is a high mix of presentation and logic and some rather confusing algorithms due to the nature of Lesson and how it is organized.

Primary coding tasks

Adding support for question class

Implement the question class code and the necessary interfaces for adding and editing questions within Lesson. The needed functionality is as follows:

  • Printing questions for attempts.
  • Grading the questions.
  • Provide a method of adding new questions to a Lesson.
    • When adding a question, display questions in course question bank to select from.
      • Provide links/tabs for creating new questions.
    • After adding a question, provide an interface to define possible jumps (This step may not be needed. Depends on the solution to the questions and jumps problem).

Changing the attempts logic

Among other Lesson table changes, one that is the most significant is changing the lesson_attempts table. Instead of storing one attempt record for every user answer, lesson_attempts table should store one record per Lesson attempt. The question_states table will replace the functionality of the original lesson_attempts table. Since this is changing such a fundamental part of Lesson, almost all of Lesson's code will have to be adapted to the new logic of attempts.

Fixing code breaks

By switching to the question class, nearly all of the current Lesson code will be broken and must be replaced or fixed. Here is a quick breakdown of foreseeable code breaks:

Database migration

Lesson tables need to be removed or changed and their old data needs to be migrated to new tables. Some of this code will be used in the restore process as well. Here is a basic overview of the upgrade process:

  • migrate lesson_pages and lesson_answer content to question tables. Note: this will only be the content, not the logic for ordering Lesson pages or any other Lesson specific data.
  • migrate lesson_attempts to question_states.
  • Re-organization of the lesson tables (see new database schema).

Unsolved problems

I have ran into some issues for which I could not find solid solutions. Please advise.

Questions and jumps

Page jumps determine the flow from one page to another and are a unique feature to Lesson. So, how does one figure out all the necessary jump definitions needed for a question? In Lesson, every answer has a jump, but this solution is not ideal. A multiple choice question for example would have two cases:

  • Single answer: a jump must be defined for each answer.
  • Multi answer: a jump would be defined for the correct answer and a jump for the wrong answer.

The follow two sections discuss possible solutions, but please feel free to suggest others. When thinking about this problem and perhaps a new solution, remember the primary goals of this project: reduce code size and simplify the Lesson code to make it easier to maintain.

Invasive solution

An invasive solution would be to modify the question class code. This is invasive because the introduced code may only be used by Lesson unless it was implemented in such a way that it would be viable for other uses. Some of the foreseeable changes would include the following:

  • Add methods to the default_questiontype class that would handle the default behavior for defining jumps. Default behavior would be two jump definitions: one for correct answers and one for incorrect answers.
  • Have a place to store the defined jumps.
  • (Optional for each question type) Override the functions in the default_questiontype class to suite the behavior of the question.


Pros for this implementation:

  • All question type code is in one place.
  • Clean implementation
  • Better work-flow for question authoring

Cons:

  • Potentially introduce code that is unusable by other modules, etc.

Noninvasive solution

Lesson would extend all question types that to handle jumps. Lesson would have its own type folder (mod/lesson/type). This type folder would be organized the same as question/type directory. Each question type would have its own folder and in that folder a questiontype.php. So, mod/lesson/type/{questiontype}/questiontype.php where {questiontype} is replaced with each question type name. The questiontype.php would extend the original question type class and add the necessary methods for handling jumps. The following methods would be added:

  • print_jump_form: accepts the possible jump values and then prints (or returns) the contents of a form. This form would then be presented to the user to define the possible jumps.
  • process_jump_form: accepts the form data from print_jump_form and organizes it into an object, string, or array. It then returns the organized data so that Lesson can store it.
  • interpret_jump: accepts the user's answer to the question and the return value from process_jump_form. This method would determine which jump Lesson should use.
  • restore_jumps: given the restore information, restore the returned value from process_jump_form. Returns the restored value so that Lesson can store it.

Example use:

Two jump definitions: correct or incorrect:

  • print_jump_form would return the following form:
 Correct answer jump: [drop-down-menu-with-lesson-jumps]
 Wrong answer jump: [drop-down-menu-with-lesson-jumps]
  • process_jump_form would accept the POST data from the above form and organize it in an array like this: array('correct' => [lesson-jump-code], 'wrong' => [lesson-jump-code]). Where [lesson-jump-code] is a Lesson page id or jump code from the [drop-down-menu-with-lesson-jumps]. This array would be returned so that Lesson could store it.
  • interpret_jump would accept the students answer and the above array. It would return the [lesson-jump-code] either associated with correct or wrong based on the student's answer.
  • restore_jumps would be called during the Lesson restore process and it would return the restored array so that Lesson could store it. Example: if each answer had a jump then the array would be defined like this: array(answerid => [lesson-jump-code] ... ). The answerid would have to be mapped to the new answerid during the restore process.


Pros for this implementation:

  • Potential Lesson specific code remains in Lesson.

Cons:

  • Work-flow would have an extra step (create question then define jumps).
  • Question authoring is more difficult.

Migration of jumps

Regardless of implementation, one problem remains: if each question potentially does not have a jump defined for each answer, then how are Lesson's questions supposed to be migrated to the new question implementation (remember, Lesson questions have one jump defined for each answer regardless if it makes sense at all)? The only solution that comes to mind is to have strict definitions for migration for the following question types that exist in Lesson:

  • Multichoice (single and multianswer)
  • Matching
  • Numerical
  • Short Answer
  • True/False
  • Essay

Note: when I say migration of jumps, I mean when upgrading the Lesson and restoring older Lessons.

Branch tables

Once a solution for the above problem has been found, I would like to discuss the possibility of replacing the functionality of branch tables with the description question type. Reason for discussing this after a solution has been found is because the solution may influence the outcome to this problem.

New database schema

{Will add later}

Discussion

If you would like to discuss topics on this page, please make a post in the lesson forum.

See also