Note:

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

Question types: Difference between revisions

From MoodleDocs
No edit summary
Line 1: Line 1:
{{Template:Question_engine_2}}
{{Template:Question_engine_2}}
This page explains how to write a question type that works with the new Moodle [[Question Engine 2|question engine]].
This page explains how to write a question type that works with the new Moodle [[Question Engine 2|question engine]], the question engine introduced with Moodle 2.1 .


For instructions on making a question type for current versions of Moodle, see [[Question_type_plugin_how_to]].
For instructions on making a question type for versions of Moodle prior to Moodle 2.1, see [[Question_type_plugin_how_to]].


Previous section: [[Developing a Question Behaviour|Developing a Question Behaviour]]
Previous section: [[Developing a Question Behaviour|Developing a Question Behaviour]]

Revision as of 12:38, 24 October 2011

This page explains how to write a question type that works with the new Moodle question engine, the question engine introduced with Moodle 2.1 .

For instructions on making a question type for versions of Moodle prior to Moodle 2.1, see Question_type_plugin_how_to.

Previous section: Developing a Question Behaviour

Note: This page is a work-in-progress. Feedback and suggested improvements are welcome. Please join the discussion on moodle.org or use the page comments.


To learn to write question types, you are highly encouraged to read the code of some of the existing question types in the Moodle code base.

Also note that all the question engine code has extensive PHP documenter comments that should explain the purpose of every class and method. This document is supposed to provide an overview of the key points to get you started. It does not attempt to duplicate all the details in the PHPdocs.

This document assumes that you understand the data model, where a question attempt comprises a number of steps, and each step has some properties like a state and a mark, and an array of submitted data.


File layout

Question types live in a folder in question/type. The layout inside this folder follows the typical layout for a Moodle plugin. For example, inside the question/type/mytype/ folder we would have:

questiontype.php
Defines the qtype_mytype class. This must extend question_type.
question.php
This contains the definition of the qtype_mytype_question class, which should extend the question_definition base class.
renderer.php
This contains the definition of the qtype_mytype_renderer class, which should extend the qtype_renderer base class.
simpletest/...
Contains the unit tests for this question type. You are strongly encouraged to write thorough unit tests to ensure the correctness of your question type.
lang/en_utf8/qtype_myqtype.php
English language strings for this question type. You can, of course, include other languages too. The language file must define at least the string giving the model a name, for example $string['addingmyqtype'] = 'Adding a My question type';, $string['editingmyqtype'] = 'Editing a My question type'; and $string['myqtype'] = 'My question type';
db/install.xml, db/upgrade.php
For creating any database tables required, as normal. See #Database_tables below.
db/access.php
Defines any capabilities required by this question type. This is very rarely needed.

Database tables

Note that question types should only have database tables for the question definition. All runtime data is managed by the question engine.

Question definitions should use the core table question, and can use the core table question_answers. You only need to define database tables if your question definition requires extra information that cannot be stored in either of these.


Question type class

This class represents the question type. It is responsible for loading and saving instances of questions of this class. It is also responsible for backing them up and restoring them. It also provides meta-data about the question type.


TODO

Question definition class

This holds the definition of a particular question of this type. There may also be some methods to perform processing. For example grade_responses.


TODO

Renderer class

Renderers are all about generating HTML output. The overall output of questions is controlled by the core_question_renderer::question(...), which in turn calls other methods of itself, the question type renderer and the behaviour renderer, to generate the various bits of output. See this overview of the parts of a question.

Once again, in what follows, I only list the methods your are most likely to want to override.


formulation_and_controls

This displays the question text, and the controls the student will use to input their response. Some question types choose to display some feedback embedded in this area, for example ticks and crosses next to parts of the student's response.

The output code must respect the question_display_options and only reveal as much information as the calling code wants revealed. For example, the teacher creating a quiz may not want the correct answer revealed until after the quiz close date. Also, when outputting the controls, you need to respect the ->readonly option.

specific_feedback

Anything returned by this method is included in the 'outcome' area of the question, it is some feedback that particularly relates to the response the student gave. This method is only called if the display options allow this to be shows, so you don't have to worry about testing that.


correct_response

This would also be included in the 'outcome' area. This should be an automatically generated (from the question definition) display of what the correct answer to the question is.


Unit tests

For a general introduction, see the Moodle unit testing documentation.

The most important parts of your question type to test are the parts of the question_definition class that process the students responses, including the compare and grade methods.

The best way to start is probably to look at the tests for some of the standard question types.


Advanced ideas

Note that there is actually no reason why you should only have a single question_definition class for your question type. You may decide, depending on the question options, to use different definition classes where question options cause questions to behave in different ways. The multiple-choice question type does this, using different definition and renderer classes for single-response and multiple-response questions (but with common subclasses). This is possible because your question type can override the question_type::make_question_instance and question_definition::get_renderer methods.


Converting a Moodle 2.0 question type

1. Change the class definition in questiontype.php from

class question_myqtype_qtype extends default_questiontype {

to

class qtype_myqtype extends question_type {


2. Create new renderer.php and question.php files, with a suitable blank class definition in them. (Perhaps copy the files from another question type, then delete everything in the class.)


3. Fill in the the question definition class, including:

3a. appropriate fields to store the question definition.

3b. create start_attempt, based on the old create_session_and_responses.

3c. create apply_attempt_state, based on the old restore_session_and_responses.

3d. Implement the grading logic get_expected_data, is_complete_response, is_gradable_response, is_same_response, grade_response, get_num_parts_right, clear_wrong_from_response. Some of this will be based on the old grade_responses method. You may also find some of the necessary code mixed into places like print_question_formulation_and_controls.

3e. Implement the reporting functionality get_correct_response, get_question_summary, summarise_response. Some of this may be related to the old grading methods.

3f. Write a test helper class to create one or more typical test instances of your question definition class.

3g. Write unit tests for the grading and reporting methods.


4. Copy all the code from print_question_formulation_and_controls and display.html, and related methods, and split it into the appropriate methods in the renderer class.


5. Write one or more walk-through tests that take instances of your question with different behaviours.


6. Implement initialise_question_instance to populate instances of your question definition class from the data returned by get_question_options.


7. Copy check_file_access from the question type class to the question definition class, and update it.


8. Delete all the old qtype_myqtype_question methods that are no longer used.

9. Add things like hints to the question_edit_myqtype_form class. Look for opportunities to improve the existing code by using the helper methods like add_combined_feedback_fields, data_preprocessing_answers.

10. Note that question_type::get_editing_head_contributions no longer exists, because it is no longer necessary with the new mechanisms for handling CSS and JavaScript in Moodle 2.x. Any styles you put in question/type/mytype/styles.css will be included on every page anyway, and you can use $PAGE->requires->js_init_call() in, for example, the form definition, to load your JavaScript.

See also

Next section: Using the question engine from a module.

  • The PHP documenter comments that explain the purposes of every method in the question engine code.
  • Back to Question Engine 2