mirror of
https://github.com/moodle/moodle.git
synced 2025-02-22 10:57:20 +01:00
334 lines
14 KiB
HTML
334 lines
14 KiB
HTML
<!DOCTYPE HTML PUBLIC>
|
|
<html>
|
|
<head>
|
|
<title>Response Storage</title>
|
|
<meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
|
|
<!--link rel="stylesheet" type="text/css" href="doc.css"-->
|
|
</head>
|
|
<body>
|
|
|
|
<h1>Response Storage</h1>
|
|
|
|
<h2>Contents</h2>
|
|
<ul class="navigation">
|
|
<li><a href='#description'>Purpose and Description</a></li>
|
|
<li><a href='#qtypemethods'>Questiontype Methods</a></li>
|
|
<li><a href='#storage'>Response Storage</a></li>
|
|
<li><a href='#runtime'>Runtime Model</a></li>
|
|
<li><a href='#qtypes'>Responses by Questiontype</a></li>
|
|
</ul>
|
|
|
|
|
|
<a name='description'></a><h2>Purpose and Description</h2>
|
|
<p>
|
|
|
|
<a href="terminology.html#responses">Responses</a> are an attribute of the
|
|
<code>$state</code> object. Questiontypes are completely free to implement the
|
|
storage mechanism of their responses (and other state information) the way they
|
|
want. Still, the standard <a href="terminology.html#responses">questiontypes</a>
|
|
all follow a similar model. The default storage model and the questiontype
|
|
specific variations are explained below.
|
|
|
|
</p><p>
|
|
|
|
The <a href="#runtime">runtime model</a> needs some more standardisation to work
|
|
generically. Therefore it imposes some constraints by convention, which are
|
|
explained later on the page.
|
|
|
|
</p>
|
|
|
|
|
|
<a name='qtypemethods'></a><h2>Questiontype Methods</h2>
|
|
<p>
|
|
|
|
The flexibility for the questiontypes to choose their response storage mechanism
|
|
freely and to convert from the storage model to the runtime model is provided by
|
|
a set of three functions, which allow to initialise the runtime
|
|
<code>$state->responses</code> field, to convert from the runtime to the storage
|
|
model and vice versa:
|
|
|
|
<ul>
|
|
<li><code>create_session_and_responses</code></li>
|
|
<li><code>restore_session_and_responses</code></li>
|
|
<li><code>save_session_and_responses</code></li>
|
|
</ul>
|
|
|
|
The following method descriptions are adapted from the phpdoc comments in
|
|
locallib.php.
|
|
|
|
</p>
|
|
|
|
<h3><code>create_session_and_responses</code></h3>
|
|
<p>
|
|
|
|
Initializes the <code>$state</code> object, in particular the
|
|
<code>$state->responses</code> field, but also any other state (or session)
|
|
information.
|
|
|
|
</p><p>
|
|
|
|
This function is called to start a question session. Empty question type
|
|
specific session data (if any) and empty response data is added to the
|
|
<code>$state</code> object. Session data is any data which must persist
|
|
throughout the quiz attempt, possibly with updates as the user interacts with
|
|
the question. This function does <strong>not</strong> create new entries in the
|
|
database for the session; a call to the <code>save_session_and_responses</code>
|
|
method will occur to do this.
|
|
</p>
|
|
|
|
<h3><code>restore_session_and_responses</code></h3>
|
|
<p>
|
|
Restores the session data and most recent responses for the given state.
|
|
|
|
</p><p>
|
|
|
|
This function loads any session data associated with the question session in the
|
|
given state from the database into the <code>$state</code> object. In particular
|
|
it loads the responses that have been saved for the given <code>$state</code>
|
|
into the <code>$state->responses</code> field.
|
|
|
|
</p><p>
|
|
|
|
Questiontypes with only a single form field for the student's response will not
|
|
need to restore the responses; the value of the <code>answer</code> field in the
|
|
<code>quiz_states</code> table is restored to <code>$state->responses['']</code>
|
|
automatically before this function is called. Questiontypes with more response
|
|
fields should override this method and set the <code>$state->responses</code>
|
|
field to an associative array of responses.
|
|
|
|
</p>
|
|
|
|
|
|
<h3><code>save_session_and_responses</code></h3>
|
|
<p>
|
|
|
|
Saves the session data and responses for the given question and state.
|
|
|
|
</p><p>
|
|
|
|
This function saves the question type specific session data from the
|
|
<code>$state</code> object to the database. In particular, for most
|
|
questiontypes, it saves the responses from the <code>$state->responses</code>
|
|
field of the <code>$state</code> object. The questiontype non-specific data for
|
|
the state has already been saved in the <code>quiz_states</code> table and the
|
|
<code>$state</code> object contains the corresponding id and sequence number,
|
|
which may be used to index a question type specific table.
|
|
|
|
</p><p>
|
|
|
|
Questiontypes with only a single form field for the student's response, which is
|
|
contained in <code>$state->responses['']</code> will not have to save this
|
|
response. It will already have been saved to the <code>answer</code> field of
|
|
the <code>quiz_states</code> table. Questiontypes with more response fields
|
|
should override this method and save the responses in their own database tables.
|
|
|
|
</p>
|
|
|
|
|
|
<a name='storage'></a><h2>Response Storage</h2>
|
|
<p>
|
|
|
|
The generic quiz module code saves the contents form the
|
|
<code>$state->responses['']</code> field to the <code>answer</code> field in the
|
|
<code>quiz_states</code> table and also automatically restores the contents of
|
|
this field to <code>$state->responses['']</code>. This means that any
|
|
questiontype, which only expects a single value as its response can skip the
|
|
implementation of the three methods described above. All questiontypes that have
|
|
multiple value responses need to implement these methods. The default
|
|
questiontypes handle this problem by serializing/de-serializing the responses
|
|
to/from the <code>answer</code> field in the <code>quiz_states</code> table.
|
|
However, it is also possible (and may be better practice) to extend the
|
|
<code>quiz_states</code> table with a questiontype specific table, i.e. take the
|
|
id of the <code>quiz_states</code> record as a foreign key in the questiontype
|
|
specific table. Because the value of <code>$state->responses['']</code> is set
|
|
to the value of the <code>answer</code> field, questiontypes that serialize
|
|
their response need to overwrite (in <code>save_session_and_responses</code>)
|
|
whatever value the generic code set this field to with their serialized value
|
|
(usually achieved with a simple <code>set_field</code>). In the method
|
|
<code>restore_session_and_responses</code> the serialized value can be read from
|
|
<code>$state->responses['']</code>. Care needs to be taken that this array value
|
|
is then unset or the whole array overwritten, so that the array does not
|
|
accidentally contain a value with the empty string index.
|
|
|
|
</p>
|
|
|
|
<a name='runtime'></a><h2>Runtime Model</h2>
|
|
<p>
|
|
|
|
The runtime model for responses dictates the structure of the
|
|
<code>$state->responses</code> array. Starting with the names of the
|
|
form elements this section goes through the relevant processing
|
|
steps and thus attempts to clarify why the keys of the
|
|
<code>$state->responses</code> array can differ for different
|
|
questiontypes; even more, it explains how the array keys are chosen and
|
|
set.
|
|
|
|
</p><p>
|
|
|
|
Although it may initially seem strange to start with the naming convention of
|
|
the form fields, the reason for this will become clear later on. The controls
|
|
(i.e. the form fields) of a question get printed by the method
|
|
<code>print_question_formulation_and_controls()</code>. The convention only
|
|
dictates that the name of the control element(s) <strong>must</strong> begin
|
|
with the value of <code>$question->name_prefix</code>. The
|
|
<code>$question->name_prefix</code> is a string starting with "resp" followed by
|
|
the question id and an underscore, e.g. resp56_. In the default case, when
|
|
there is only a single control element (this includes the case of a list of equally named
|
|
radio buttons), no postfix is appended to the name prefix. For questiontypes
|
|
that allow or require multiple form elements, an arbitrary string can be appended
|
|
to the name prefix to form the name of these form elements. The postfix must not
|
|
include any relational data
|
|
(i.e. ids of records in the <code>quiz_answers</code> table), because this can
|
|
lead to problems with regrading of versioned questions.
|
|
|
|
</p><p>
|
|
|
|
After the printing of the question the server only sees it again when it is
|
|
submitted. So the submitted data will contain several values indexed by strings
|
|
starting with respXX_. Upon submission, the function
|
|
<code>quiz_process_responses()</code> is called, which assigns the submitted
|
|
responses to the state of the question with id XX, using the postfix (i.e.
|
|
everything after the underscore) as array keys. In the default case with
|
|
only one control element the name only consists of the name prefix. This
|
|
explains why the default index of the <code>$state->responses</code> array is
|
|
the empty string. The value of each array element is obviously the value that
|
|
was submitted by the form, basically a raw response.
|
|
|
|
</p><p>
|
|
|
|
The function <code>quiz_process_responses()</code> in turn calls the
|
|
questiontype specific method <code>grade_responses()</code> to assign
|
|
a grade to the submitted responses and
|
|
<code>compare_responses()</code> to determine whether the response was
|
|
identical to the previous submission and to avoid regrading the same
|
|
responses repeatedly. These questiontype specific functions need to
|
|
be aware of the expected keys of the
|
|
<code>$state->responses</code> array.
|
|
|
|
</p><p>
|
|
|
|
Finally, the methods <code>restore_session_and_responses()</code> and
|
|
<code>save_session_and_responses()</code> also need to know the questiontype
|
|
specific layout of the <code>$state->responses</code> array and restore or save
|
|
the information, e.g. by converting from or to the data representation.
|
|
|
|
<a name='qtypes'></a><h2>Responses by Questiontype</h2>
|
|
<h3>Calculated</h3>
|
|
<p>
|
|
|
|
The calculated questiontype inherits its methods
|
|
<code>create_session_and_responses()</code>,
|
|
<code>restore_session_and_responses()</code> and
|
|
<code>save_session_and_responses()</code> from the abstract dataset
|
|
dependent questiontype. This questiontype serializes the information
|
|
of the chosen dataset together with the (single) response value into
|
|
a string of the format datasetXX-RESPONSE, where dataset is the
|
|
actual string "dataset", XX is the number of the chosen dataset item
|
|
and RESPONSE is the value that was received from the submitted form.
|
|
|
|
</p>
|
|
|
|
<h3>Description</h3>
|
|
<p>The description questiontype does not have responses.</p>
|
|
|
|
<h3>Match</h3>
|
|
<p>
|
|
|
|
The matching questiontype stores needs to store information about the order of
|
|
its subquestions and the selected responses. Because each subquestion is
|
|
identified by one record in the <code>quiz_match_sub</code> table, the ids of
|
|
this table are used to identify both the question and the response part. For
|
|
each subquestion a '-'-separated pair is created, giving first the id of the
|
|
record that provided the subquestion and then the id of the record that provided
|
|
the selected response. E.g. 1-3 means that the answer of the third question was
|
|
selected for the first subquestion. Correct responses are always pairs of
|
|
identical ids, e.g 2-2. If no response is selected, the second id in the pair is
|
|
set to '0'. These pairs are then put into a comma separated list to allow each
|
|
subquestion to store a response.
|
|
|
|
</p>
|
|
|
|
<h3>Multianswer</h3>
|
|
<p>
|
|
|
|
The serialized format of multianswer questions is a comma separated
|
|
list of pairs. Each pair saves the response for one of the
|
|
subquestions and is itself separated with a hyphen ('-'). In front
|
|
of the hyphen there is the sequence number of the subquestion
|
|
(starting at 1 incremented by the order the subquestions appear in
|
|
the text). After the hyphen is the raw response, that was submitted
|
|
by the student. The serialized format could look like the following
|
|
example:<br /> 1-34,2-Napoleon,3-4,4-correct response,5-1<br /> All
|
|
commas and hyphens that are part of the raw answer are HTML entity
|
|
encoded to avoid problems.
|
|
|
|
</p>
|
|
|
|
<h3>Multichoice</h3>
|
|
<p>The multichoice questiontype stores both the order of the choices and the
|
|
selected choices. Storing the order is optional (mainly to provide backward
|
|
compatibility with previous versions of this questiontype). The order is stored
|
|
as a comma separated list of answer ids (i.e. form the <code>quiz_answers</code>
|
|
table). It is separated with a colon (':') from the selected responses, which
|
|
are also stored as a comma separated list of answer ids. Note that the list of
|
|
selected responses is usually shorter (and often contains only one id) than the
|
|
list that provides the order.</p>
|
|
|
|
<h3>Numerical</h3>
|
|
<p>
|
|
|
|
The numerical questiontype, which inherits the function
|
|
<code>print_question_formulation_and_controls()</code> from the shortanswer
|
|
questiontype, has only one response field, so its responses are handled by the
|
|
default questiontype. The response is stored without any modifications in the
|
|
<code>answer</code> field of the table <code>quiz_states</code>.
|
|
|
|
</p>
|
|
|
|
<h3>Random</h3>
|
|
<p>
|
|
|
|
The random questiontype saves one state with a question id in the
|
|
<code>answer</code> field to indicate which question was randomly selected. From
|
|
that point onwards only states for the chosen question are saved.
|
|
|
|
</p>
|
|
|
|
<h3>RandomSAMatch</h3>
|
|
<p>
|
|
|
|
The random shortanswer matching questiontype reuses the <code>
|
|
save_session_and_responses</code> method of the matching questiontype and
|
|
therefore stores its responses in the same format. The difference is that the
|
|
first id in the pair is the question id (<code>quiz_questions</code>) of the
|
|
selected shortanswer and the second id is the id of the first correct answer
|
|
that is found ofr that shortanswer question in the <code>quiz_answers</code>
|
|
table.
|
|
|
|
</p>
|
|
|
|
|
|
<h3>Shortanswer</h3>
|
|
<p>
|
|
|
|
The shortanswer questiontype is the ideal example of the default case. It does
|
|
not overwrite any of the default implementations of the three methods mentioned
|
|
above, because it uses the default <code>$state->responses</code> array indexed
|
|
with the empty string. The value entered into the shortanswer input field is
|
|
entered directly into the <code>answer</code> field.
|
|
|
|
</p>
|
|
|
|
<h3>Truefalse</h3>
|
|
<p>
|
|
|
|
The true/false questiontype stores a single answer id (from the table <code>
|
|
quiz_answers</code>) in the <code>answer</code> field. Each true/false question
|
|
defines two answer records, one for the 'true' option, one for the 'false'
|
|
option, so either of these two ids gets stored as response.
|
|
|
|
</p>
|
|
|
|
</body>
|
|
</html>
|