moodle/mod/quiz/doc/attempt.html

217 lines
9.3 KiB
HTML
Raw Normal View History

<!DOCTYPE HTML PUBLIC>
<html>
<head>
<title>Attempt.php</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>Attempt.php</h1>
<h2>Contents</h2>
<ul>
<a href='#description'><li>Description and purpose</li></a>
<a href='#simple'><li>A simplified perspective</li></a>
<ul>
<a href='#simple_start'><li>Starting a new attempt</li></a>
<a href='#simple_finish'><li>Finishing an attempt</li></a>
</ul>
<a href='#complicated'><li>A more complicated perspective</li></a>
</ul>
<a name="description"></a><h2>Description and purpose</h2>
<p>
The attempt.php script is one of the most complicated scripts of the
quiz module. It is responsible for displaying questions to a user,
to evaluate and grade the users' responses and additionally it needs
to take various quiz settings into account and change the behaviour
of the script accordingly. This script, which is vital for the
functioning of the quiz module, is explained in this document in some
detail in order to provide some context and examples for the use of
the question/state model and to illustrate some of the functions
provided in locallib.php.
</p><p>
In addition to the immediate benefit of explaining what happens in attempt.php,
this piece of documentation should provide an entry point to the quiz module
code. A number of functions are used in attempt.php that are likely to be used
in other scripts as well.
</p><p>
Although the attempt.php script is useful for understanding how user
interactions are handled, in order to gain an understanding of the
teacher interface for editing quizzes and questions you should look at edit.php.
</p>
<a name="simple"></a><h2>A simplified perspective</h2>
<p>
From a simple functional point of view, the responsibilities of attempt.php is
the handling of attempts at a quiz. This includes displaying questions and
storing data provided or generated by the users. The interaction could be
limited to opening the page and thus creating a new attempt and submitting the
responses back to the server, which causes the responses to be graded. While the
script is actually more sophisticated and allows to interrupt and continue
attempts, this two step scenario provides a good starting point and covers the
core functionality.
</p>
<a name='simple_start'></a><h3>Starting a new attempt</h3>
<p>
When a new attempt is started the attempt object is created by the function
<code>quiz_create_attempt()</code> (line 183). It returns an empty <code>
$attempt</code> object, which is stored in the database immediately to record
the fact that the student has seen the questions.
</p><p>
The next step is to load up all questions and to create initial states for all
of them. Loading up the questions is a two step process: first the question
records are extracted from the database, then the function <code>
quiz_get_questions_options()</code> is called. This attaches the name_prefix
field and calls the questiontype specific <code>get_question_options()</code>
method for each question record in order to add any required data.
</p><pre>
// Load the questions
if (!$questions = get_records_sql($sql)) {
...
}
// Load the question type specific information
if (!quiz_get_question_options($questions)) {
...
}
// Restore the question sessions to their most recent states
// creating new sessions where required
if (!$states = quiz_get_states($questions, $attempt)) {
...
}
</pre><p>
After all questions are correctly initialised a state object is created for
each by the function <code>quiz_get_states()</code>. This
function is responsible for providing a state for each question and creates a
new state if there isn't one to be restored. Any newly states are added
to the database right away.
</p><p>
At this point all the required data has been generated or loaded, so the last step is
to print the page. The printing happens towards the end of the attempt.php
script and, apart from a simple call to <code>print_heading()</code> (line 409),
is done in a loop through all the question records by calling <code>
quiz_print_quiz_question()</code> (line 461), which is just a shorthand for
calling the questiontype specific <code>print_question()</code> method. So, quite
conveniently, each question is responsible for printing itself. To round up the
printing, submit buttons and a footer are printed to the bottom of the page.
</p>
<a name='simple_finish'></a><h3>Processing responses</h3>
<p>
The next logical step after creating and displaying an attempt is that the user
enters answers for all questions and submits them for marking. Now it is not
necessary to create a new attempt, because there is already an open existing one
in the database and the same holds for each question's state. So this time the
attempt record is loaded from the database. The questions are loaded in the same
way, by querying for the question records an then attaching any required
questiontype specific fields by calling the function <code>
quiz_get_question_options()</code>. Now the call to the function <code>
quiz_get_states()</code> does actually restore the states from the
database rather than generate new ones, so the same code works for the two
scenarios, creating and closing an attempt.
</p><p>
Now that all data concerning the attempt under discussion has been loaded, the
responses submitted by the student come to the scene. For each
question they need to be evaluated and graded. The first step here
is to determine how to deal with each question and the associated
responses. In the simplified case this is clear; all responses need
to be graded, the grades stored and then the attempt needs to be
closed. However, there are more complicated cases, so the function
<code> quiz_extract_responses()</code> is called to create the
<code>$actions</code> array, which acts as a set of instructions for
the function <code>quiz_process_responses()</code>, a quite
complicated function, which encapsulates the entire response
processing for one question and calls out to the questiontype
specific <code>grade_responses()</code> method for grading.
</p><p>
After all submitted responses have been processed, the questions are rendered
in the new states. An exception is if the student has requested to close the
attempt (or if it is closed automatically due to a time limit). In this case
the attempt is closed by setting the
<code>timefinish</code> field to the current time. After this the user is
redirected to review.php, which, depending on the quiz review settings, shows
the questions including the student's responses, feedback, grades and correct
answers.
</p>
<a name="complicated"></a><h2>A more complicated perspective</h2>
<p>
Before an attempt may be started there are a series of mandatory and optional
checks, to determine if the user is allowed to attempt the quiz. In addition to
these checks, the page display and functionality are slightly different for
users with and without teacher privileges. Also, when the quiz is set to start
in "secure" mode (the $quiz->popup option), the printing of the page is slightly
different. Including all of these scenarios evidently complicates the structure
of the attempt.php script, deviating from the simple scenario described above.
</p><p>
First of all, access to the quiz is denied to guests. Additionally it is
possible to restrict acces to an IP range ($quiz->subnet) and to set up a
password for the quiz ($quiz->password). In both cases users that can't pass the
required tests are denied access.
</p><p>
When a teacher "attempts" a quiz there is a tab navigation facility at the top
of the page, which allows the teacher to jump between reviewing, previewing and
editing the quiz (and possibly even more options). The teacher interface also
contains a button to start a new attempt, which is not present on the student
interface. Teachers' attempts are automatically marked as previews, which means
that old attempts are automatically deleted when a new attempt is started. It
also prevents previews to show up in the students' answers review and preview
attempts don't block the possibility of editing the quiz, while students'
attempts do.
</p><p>
Further complication is introduced by the feature to allow multiple pages with
questions and navigation between these pages. This requieres mechanisms to
determine which questions are on which page, which page is currently displayed
and which page needs to be viewed next. This is not too hard to achieve,
however, one subtlety should be noted: when the attempt is closed it is
necessary to load all questions and their most recent states before they are
marked, whereas in the case of navgation only the questions and related states
of the page that was displayed before are loaded, processed and saved; and the
questions and states for the next page are loaded.
</p><p>
Towards the end of the script there are two blocks of code that are responsible
for timed quizzes ($quiz->timelimit). The first block prints the start element
of the form using javascript to make sure that javascript is enabled (which
obviously doesn't help a lot, because the quiz is printed as usual, only the
submit won't work). The second block includes the file jstimer.php, which prints
a timer that counts down and causes an auto-submit when time is up.
</p>
</body>
</html>