/**
  * Generate the display of a question in a particular state, and with certain
  * display options. Normally you do not call this method directly. Intsead
  * you call {@link question_usage_by_activity::render_question()} which will
  * call this method with appropriate arguments.
  *
  * @param question_attempt $qa the question attempt to display.
  * @param qbehaviour_renderer $behaviouroutput the renderer to output the behaviour
  *      specific parts.
  * @param qtype_renderer $qtoutput the renderer to output the question type
  *      specific parts.
  * @param question_display_options $options controls what should and should not be displayed.
  * @param string|null $number The question number to display. 'i' is a special
  *      value that gets displayed as Information. Null means no number is displayed.
  * @return string HTML representation of the question.
  */
 public function question(question_attempt $qa, qbehaviour_renderer $behaviouroutput, qtype_renderer $qtoutput, question_display_options $options, $number)
 {
     //start a new output buffer
     $output = '';
     //add the quesiton number (TODO: style?)
     //$output .= '<strong>' . $number .'.</strong>&nbsp; &nbsp;';
     $output .= html_writer::start_tag('table', array('style' => 'width: 100%; padding-bottom: 4px;'));
     $output .= html_writer::start_tag('tr', array());
     $output .= html_writer::tag('td', $number . '.', array('valign' => 'top', 'width' => '10%', 'style' => 'padding-right: 10px;'));
     $output .= html_writer::start_tag('td', array('width' => '90%'));
     //get the question from the attempt object
     $question = $qa->get_question();
     $pragmas = self::extract_pragmas($question->format_questiontext($qa));
     //add the question's formulation
     $output .= $this->formulation($qa, $behaviouroutput, $qtoutput, $options);
     //an indication of output, if appropriate
     $output .= $this->outcome($qa, $behaviouroutput, $qtoutput, $options);
     //any manual comments, if appropriate
     $output .= $this->manual_comment($qa, $behaviouroutput, $qtoutput, $options);
     //the user's response history, if appropriate
     $output .= $this->response_history($qa, $behaviouroutput, $qtoutput, $options);
     $output .= html_writer::end_tag('td');
     $output .= html_writer::end_tag('tr');
     $output .= html_writer::end_tag('table');
     //if a pragma exists specifying the space after a given quesiton, use it; otherwise, assume 5px
     //$space_after = array_key_exists('space_after', $pragmas) ? $pragmas['space_after'] : '5px';
     $space_after = array_key_exists('space_after', $pragmas) ? $pragmas['space_after'] : 0;
     //and add a spacer after the given question
     if ($space_after !== 0) {
         $output .= html_writer::tag('div', '&nbsp;', array('style' => 'height: ' . $space_after . ';'));
     }
     //return the contents of the output buffer
     return $output;
 }
 protected function embedded_element(question_attempt $qa, $place, question_display_options $options)
 {
     $question = $qa->get_question();
     $group = $question->places[$place];
     $fieldname = $question->field($place);
     $value = $qa->get_last_qt_var($question->field($place));
     $attributes = array('id' => $this->box_id($qa, 'p' . $place));
     $groupclass = 'group' . $group;
     if ($options->readonly) {
         $attributes['disabled'] = 'disabled';
     }
     $orderedchoices = $question->get_ordered_choices($group);
     $selectoptions = array();
     foreach ($orderedchoices as $orderedchoicevalue => $orderedchoice) {
         $selectoptions[$orderedchoicevalue] = $orderedchoice->text;
     }
     $feedbackimage = '';
     if ($options->correctness) {
         $response = $qa->get_last_qt_data();
         if (array_key_exists($fieldname, $response)) {
             $fraction = (int) ($response[$fieldname] == $question->get_right_choice_for($place));
             $attributes['class'] = $this->feedback_class($fraction);
             $feedbackimage = $this->feedback_image($fraction);
         }
     }
     $selecthtml = html_writer::select($selectoptions, $qa->get_qt_field_name($fieldname), $value, get_string('choosedots'), $attributes) . ' ' . $feedbackimage;
     return html_writer::tag('span', $selecthtml, array('class' => 'control ' . $groupclass));
 }
 public function manual_comment(question_attempt $qa, question_display_options $options)
 {
     if ($options->manualcomment != question_display_options::EDITABLE) {
         return '';
     }
     $question = $qa->get_question();
     return html_writer::nonempty_tag('div', $question->format_text($question->graderinfo, $question->graderinfo, $qa, 'qtype_poodllrecording', 'graderinfo', $question->id), array('class' => 'graderinfo'));
 }
Exemple #4
0
 /**
  * Normally you should not call this constuctor directly. The appropriate
  * behaviour object is created automatically as part of
  * {@link question_attempt::start()}.
  * @param question_attempt $qa the question attempt we will be managing.
  * @param string $preferredbehaviour the type of behaviour that was actually
  *      requested. This information is not needed in most cases, the type of
  *      subclass is enough, but occasionally it is needed.
  */
 public function __construct(question_attempt $qa, $preferredbehaviour) {
     $this->qa = $qa;
     $this->question = $qa->get_question();
     if (!$this->is_compatible_question($this->question)) {
         throw new coding_exception('This behaviour (' . $this->get_name() .
                 ') cannot work with this question (' . get_class($this->question) . ')');
     }
 }
 public function correct_response(question_attempt $qa)
 {
     $question = $qa->get_question();
     $answer = $question->get_matching_answer($question->get_correct_response());
     if (!$answer) {
         return '';
     }
     return get_string('correctansweris', 'qtype_shortanswer', s($answer->answer));
 }
 /**
  * Normally you should not call this constuctor directly. The appropriate
  * behaviour object is created automatically as part of
  * {@link question_attempt::start()}.
  * @param question_attempt $qa the question attempt we will be managing.
  * @param string $preferredbehaviour the type of behaviour that was actually
  *      requested. This information is not needed in most cases, the type of
  *      subclass is enough, but occasionally it is needed.
  */
 public function __construct(question_attempt $qa, $preferredbehaviour)
 {
     $this->qa = $qa;
     $this->question = $qa->get_question();
     $requiredclass = $this->required_question_definition_type();
     if (!$this->question instanceof $requiredclass) {
         throw new coding_exception('This behaviour (' . $this->get_name() . ') cannot work with this question (' . get_class($this->question) . ')');
     }
 }
 public function specific_feedback(question_attempt $qa)
 {
     $question = $qa->get_question();
     $response = array();
     foreach ($question->get_parameters() as $param) {
         $response['answer_' . $param] = $qa->get_last_qt_var('answer_' . $param);
     }
     $question->compute_feedbackperconditions($response);
     return $question->computedfeedbackperconditions;
 }
 public function controls(question_attempt $qa, question_display_options $options)
 {
     $question = $qa->get_question();
     if (!empty($question->precheck)) {
         $buttons = $this->precheck_button($qa, $options) . "\n" . $this->submit_button($qa, $options);
     } else {
         $buttons = $this->submit_button($qa, $options);
     }
     return $buttons;
 }
Exemple #9
0
 /**
  * Generates the specific feedback from the database when the attempt is finished and the question is answered.
  */
 public function specific_feedback(question_attempt $qa)
 {
     global $DB, $CFG;
     // get feedback from the database
     $record = $DB->get_record('qtype_javaunittest_feedback', array('questionattemptid' => $qa->get_database_id()), 'feedback');
     if ($record === false) {
         return '';
     }
     $feedback = $record->feedback;
     $question = $qa->get_question();
     return $question->format_text($feedback, 0, $qa, 'question', 'answerfeedback', 1);
 }
Exemple #10
0
 public function correct_response(question_attempt $qa)
 {
     $question = $qa->get_question();
     $answer = $question->get_correct_response();
     if (!$answer) {
         return '';
     }
     $response = $answer['answer'];
     if ($question->unitdisplay != qtype_numerical::UNITNONE && $question->unitdisplay != qtype_numerical::UNITINPUT) {
         $response = $question->ap->add_unit($response);
     }
     return get_string('correctansweris', 'qtype_shortanswer', $response);
 }
 public function formulation_and_controls(question_attempt $qa, question_display_options $options)
 {
     $question = $qa->get_question();
     $output = '';
     foreach ($question->textfragments as $i => $fragment) {
         if ($i > 0) {
             $index = $question->places[$i];
             $output .= $this->subquestion($qa, $options, $index, $question->subquestions[$index]);
         }
         $output .= $question->format_text($fragment, $question->questiontextformat, $qa, 'question', 'questiontext', $question->id);
     }
     $this->page->requires->js_init_call('M.qtype_multianswer.init', array('#q' . $qa->get_slot()), false, array('name' => 'qtype_multianswer', 'fullpath' => '/question/type/multianswer/module.js', 'requires' => array('base', 'node', 'event', 'overlay')));
     return $output;
 }
Exemple #12
0
 public function correct_response(question_attempt $qa)
 {
     $question = $qa->get_question();
     $correctanswer = '';
     foreach ($question->textfragments as $i => $fragment) {
         if ($i > 0) {
             $group = $question->places[$i];
             $choice = $question->choices[$group][$question->rightchoices[$i]];
             $correctanswer .= '[' . str_replace('-', '&#x2011;', $choice->text) . ']';
         }
         $correctanswer .= $fragment;
     }
     if (!empty($correctanswer)) {
         return get_string('correctansweris', 'qtype_gapselect', $question->format_text($correctanswer, $question->questiontextformat, $qa, 'question', 'questiontext', $question->id));
     }
 }
 /**
  * Display the information about the penalty calculations.
  * @param question_attempt $qa the question attempt.
  * @param object $mark contains information about the current mark.
  * @param question_display_options $options display options.
  */
 protected function penalty_info(question_attempt $qa, $mark, question_display_options $options)
 {
     if (!$qa->get_question()->penalty) {
         return '';
     }
     $output = '';
     // print details of grade adjustment due to penalties
     if ($mark->raw != $mark->cur) {
         $output .= ' ' . get_string('gradingdetailsadjustment', 'qbehaviour_adaptive', $mark);
     }
     // print info about new penalty
     // penalty is relevant only if the answer is not correct and further attempts are possible
     if (!$qa->get_state()->is_finished()) {
         $output .= ' ' . get_string('gradingdetailspenalty', 'qbehaviour_adaptive', format_float($qa->get_question()->penalty, $options->markdp));
     }
     return $output;
 }
 /**
  * Generate the display of the formulation part of the question. This is the
  * area that contains the quetsion text, and the controls for students to
  * input their answers. Some question types also embed bits of feedback, for
  * example ticks and crosses, in this area.
  *
  * @param question_attempt $qa the question attempt to display.
  * @param question_display_options $options controls what should and should not be displayed.
  * @return string HTML fragment.
  */
 public function formulation_and_controls(question_attempt $qa, question_display_options $options)
 {
     $question = $qa->get_question();
     $response = $qa->get_last_qt_data();
     $table = new html_table();
     $table->attributes['class'] = 'matrix';
     $table->head = array();
     $table->head[] = '';
     foreach ($question->cols as $col) {
         $table->head[] = self::matrix_header($col);
     }
     if ($options->correctness) {
         $table->head[] = '';
     }
     foreach ($question->rows as $row) {
         $row_data = array();
         $row_data[] = self::matrix_header($row);
         foreach ($question->cols as $col) {
             $key = $question->key($row, $col);
             $cell_name = $qa->get_field_prefix() . $key;
             $is_readonly = $options->readonly;
             $is_checked = $question->is_answered($response, $row, $col);
             if ($question->multiple) {
                 $cell = self::checkbox($cell_name, $is_checked, $is_readonly);
             } else {
                 $cell = self::radio($cell_name, $col->id, $is_checked, $is_readonly);
             }
             if ($options->correctness) {
                 $weight = $question->weight($row, $col);
                 $cell .= $this->feedback_image($weight);
             }
             $row_data[] = $cell;
         }
         if ($options->correctness) {
             $row_grade = $question->grading()->grade_row($question, $row, $response);
             $feedback = $row->feedback;
             $feedback = strip_tags($feedback) ? $feedback : '';
             $row_data[] = $this->feedback_image($row_grade) . $feedback;
         }
         $table->data[] = $row_data;
         //$row_index++;
     }
     $result = $question->questiontext;
     $result .= html_writer::table($table, true);
     return $result;
 }
 public function formulation_and_controls(question_attempt $qa, question_display_options $options)
 {
     $question = $qa->get_question();
     $questiontext = $question->format_questiontext($qa);
     $placeholder = false;
     if (preg_match('/_____+/', $questiontext, $matches)) {
         $placeholder = $matches[0];
     }
     $input = '**subq controls go in here**';
     if ($placeholder) {
         $questiontext = substr_replace($questiontext, $input, strpos($questiontext, $placeholder), strlen($placeholder));
     }
     $result = html_writer::tag('div', $questiontext, array('class' => 'qtext'));
     /* if ($qa->get_state() == question_state::$invalid) {
            $result .= html_writer::nonempty_tag('div',
                    $question->get_validation_error(array('answer' => $currentanswer)),
                    array('class' => 'validationerror'));
        }*/
     return $result;
 }
 /**
  * Store an entire {@link question_attempt} in the database,
  * including all the question_attempt_steps that comprise it.
  * @param question_attempt $qa the question attempt to store.
  * @param object $context the context of the owning question_usage_by_activity.
  */
 public function insert_question_attempt(question_attempt $qa, $context)
 {
     $record = new stdClass();
     $record->questionusageid = $qa->get_usage_id();
     $record->slot = $qa->get_slot();
     $record->behaviour = $qa->get_behaviour_name();
     $record->questionid = $qa->get_question()->id;
     $record->variant = $qa->get_variant();
     $record->maxmark = $qa->get_max_mark();
     $record->minfraction = $qa->get_min_fraction();
     $record->flagged = $qa->is_flagged();
     $record->questionsummary = $qa->get_question_summary();
     $record->rightanswer = $qa->get_right_answer_summary();
     $record->responsesummary = $qa->get_response_summary();
     $record->timemodified = time();
     $record->id = $this->db->insert_record('question_attempts', $record);
     foreach ($qa->get_step_iterator() as $seq => $step) {
         $this->insert_question_attempt_step($step, $record->id, $seq, $context);
     }
 }
 public function correct_response(question_attempt $qa)
 {
     if ($qa->get_state()->is_correct()) {
         // The answer was correct so we don't need to do anything further.
         return '';
     }
     $question = $qa->get_question();
     $stemorder = $question->get_stem_order();
     $choices = $this->format_choices($qa, true);
     $table = new html_table();
     $table->attributes['class'] = 'generaltable correctanswertable';
     $table->size = array('50%', '50%');
     foreach ($stemorder as $key => $stemid) {
         $row = new html_table_row();
         $row->cells[] = $question->format_text($question->stems[$stemid], $question->stemformat[$stemid], $qa, 'qtype_ddmatch', 'subquestion', $stemid);
         $row->cells[] = $choices[$question->get_right_choice_for($stemid)];
         $table->data[] = $row;
     }
     return get_string('correctansweris', 'qtype_match', html_writer::table($table));
 }
 /**
  * Display the information about the penalty calculations.
  * @param question_attempt $qa the question attempt.
  * @param object $mark contains information about the current mark.
  * @param question_display_options $options display options.
  */
 protected function penalty_info(question_attempt $qa, $mark, question_display_options $options)
 {
     $currentpenalty = $qa->get_question()->penalty * $qa->get_max_mark();
     $totalpenalty = $currentpenalty * $qa->get_last_behaviour_var('_try', 0);
     if ($currentpenalty == 0) {
         return '';
     }
     $output = '';
     // Print details of grade adjustment due to penalties
     if ($mark->raw != $mark->cur) {
         $output .= ' ' . get_string('gradingdetailsadjustment', 'qbehaviour_adaptive', $mark);
     }
     // Print information about any new penalty, only relevant if the answer can be improved.
     if ($qa->get_behaviour()->is_state_improvable($qa->get_state())) {
         $output .= ' ' . get_string('gradingdetailspenalty', 'qbehaviour_adaptive', format_float($currentpenalty, $options->markdp));
         // Print information about total penalties so far, if larger than current penalty.
         if ($totalpenalty > $currentpenalty) {
             $output .= ' ' . get_string('gradingdetailspenaltytotal', 'qbehaviour_adaptive', format_float($totalpenalty, $options->markdp));
         }
     }
     return $output;
 }
Exemple #19
0
 public function formulation_and_controls(question_attempt $qa, question_display_options $options)
 {
     $question = $qa->get_question();
     $output = '';
     $subquestions = array();
     foreach ($question->textfragments as $i => $fragment) {
         if ($i > 0) {
             $index = $question->places[$i];
             $token = 'qtypemultianswer' . $i . 'marker';
             $token = '<span class="nolink">' . $token . '</span>';
             $output .= $token;
             $subquestions[$token] = $this->subquestion($qa, $options, $index, $question->subquestions[$index]);
         }
         $output .= $fragment;
     }
     $output = $question->format_text($output, $question->questiontextformat, $qa, 'question', 'questiontext', $question->id);
     $output = str_replace(array_keys($subquestions), array_values($subquestions), $output);
     if ($qa->get_state() == question_state::$invalid) {
         $output .= html_writer::nonempty_tag('div', $question->get_validation_error($qa->get_last_qt_data()), array('class' => 'validationerror'));
     }
     $this->page->requires->js_init_call('M.qtype_multianswer.init', array('#q' . $qa->get_slot()), false, array('name' => 'qtype_multianswer', 'fullpath' => '/question/type/multianswer/module.js', 'requires' => array('base', 'node', 'event', 'overlay')));
     return $output;
 }
Exemple #20
0
 protected function edit_question_link(question_attempt $qa, question_display_options $options)
 {
     global $CFG;
     if (empty($options->editquestionparams)) {
         return '';
     }
     $params = $options->editquestionparams;
     if ($params['returnurl'] instanceof moodle_url) {
         $params['returnurl'] = $params['returnurl']->out_as_local_url(false);
     }
     $params['id'] = $qa->get_question()->id;
     $editurl = new moodle_url('/question/question.php', $params);
     return html_writer::tag('div', html_writer::link($editurl, $this->pix_icon('t/edit', get_string('edit'), '', array('class' => 'iconsmall')) . get_string('editquestion', 'question')), array('class' => 'editquestion'));
 }
 public function test_constructor_sets_maxmark()
 {
     $qa = new question_attempt($this->question, $this->usageid);
     $this->assertSame($this->question, $qa->get_question());
     $this->assertEquals(3, $qa->get_max_mark());
 }
 protected function hidden_fields(question_attempt $qa)
 {
     $question = $qa->get_question();
     $hiddenfieldshtml = '';
     $inputids = new stdClass();
     $responsefields = array_keys($question->get_expected_data());
     foreach ($responsefields as $responsefield) {
         $hiddenfieldshtml .= $this->hidden_field_for_qt_var($qa, $responsefield);
     }
     return $hiddenfieldshtml;
 }
Exemple #23
0
 protected function get_state_string(question_attempt $qa, $showcorrectness)
 {
     if ($qa->get_question()->length > 0) {
         return $qa->get_state_string($showcorrectness);
     }
     // Special case handling for 'information' items.
     if ($qa->get_state() == question_state::$todo) {
         return get_string('notyetviewed', 'quiz');
     } else {
         return get_string('viewed', 'quiz');
     }
 }
 protected function penalty_info(question_attempt $qa, $mark, question_display_options $options)
 {
     if (!$qa->get_question()->penalty && !$qa->get_last_behaviour_var('_hashint', false)) {
         // No penalty for the attempts and no hinting done.
         return '';
     }
     $output = '';
     // Print details of grade adjustment due to penalties.
     if ($mark->raw != $mark->cur) {
         $output .= ' ' . get_string('gradingdetailsadjustment', 'qbehaviour_adaptive', $mark);
     }
     // Print information about any new penalty, only relevant if the answer can be improved.
     if ($qa->get_behaviour()->is_state_improvable($qa->get_state())) {
         $output .= ' ' . get_string('gradingdetailspenalty', 'qbehaviour_adaptive', format_float($qa->get_last_step()->get_behaviour_var('_penalty'), $options->markdp));
     }
     return $output;
 }
 public function get_marked_gaps(question_attempt $qa, question_display_options $options)
 {
     $marked_gaps = array();
     $question = $qa->get_question();
     $correct_gaps = array();
     foreach ($question->textfragments as $place => $fragment) {
         if ($place < 1) {
             continue;
         }
         $fieldname = $question->field($place);
         $rightanswer = $question->get_right_choice_for($place);
         if ($options->correctness or $options->numpartscorrect) {
             $response = $qa->get_last_qt_data();
             if (array_key_exists($fieldname, $response)) {
                 if ($question->is_correct_response($response[$fieldname], $rightanswer)) {
                     $marked_gaps[$fieldname]['value'] = $response[$fieldname];
                     $marked_gaps[$fieldname]['fraction'] = 1;
                     $correct_gaps[] = $response[$fieldname];
                 } else {
                     $marked_gaps[$fieldname]['value'] = $response[$fieldname];
                     $marked_gaps[$fieldname]['fraction'] = 0;
                 }
             }
         }
     }
     $arr_unique = array_unique($correct_gaps);
     $arr_duplicates = array_diff_assoc($correct_gaps, $arr_unique);
     foreach ($marked_gaps as $fieldname => $gap) {
         if (in_array($gap['value'], $arr_duplicates)) {
             $marked_gaps[$fieldname]['duplicate'] = 'true';
         } else {
             $marked_gaps[$fieldname]['duplicate'] = 'false';
         }
     }
     return $marked_gaps;
 }
Exemple #26
0
 public function correct_response(question_attempt $qa)
 {
     $question = $qa->get_question();
     $stemorder = $question->get_stem_order();
     $choices = $this->format_choices($question);
     $right = array();
     foreach ($stemorder as $key => $stemid) {
         if (!isset($choices[$question->get_right_choice_for($stemid)])) {
             continue;
         }
         $right[] = $question->make_html_inline($this->format_stem_text($qa, $stemid)) . ' – ' . $choices[$question->get_right_choice_for($stemid)];
     }
     if (!empty($right)) {
         return get_string('correctansweris', 'qtype_match', implode(', ', $right));
     }
 }
Exemple #27
0
    public function correct_response(question_attempt $qa) {
        $question = $qa->get_question();
        $answer = $question->get_correct_answer();
        if (!$answer) {
            return '';
        }

        $response = str_replace('.', $question->ap->get_point(), $answer->answer);
        if ($question->unitdisplay != qtype_numerical::UNITNONE) {
            $response = $question->ap->add_unit($response);
        }

        return get_string('correctansweris', 'qtype_shortanswer', $response);
    }
Exemple #28
0
 /**
  * Store an entire {@link question_attempt} in the database,
  * including all the question_attempt_steps that comprise it.
  * @param question_attempt $qa the question attempt to store.
  * @param context $context the context of the owning question_usage_by_activity.
  */
 public function insert_question_attempt(question_attempt $qa, $context)
 {
     $record = new stdClass();
     $record->questionusageid = $qa->get_usage_id();
     $record->slot = $qa->get_slot();
     $record->behaviour = $qa->get_behaviour_name();
     $record->questionid = $qa->get_question()->id;
     $record->variant = $qa->get_variant();
     $record->maxmark = $qa->get_max_mark();
     $record->minfraction = $qa->get_min_fraction();
     $record->maxfraction = $qa->get_max_fraction();
     $record->flagged = $qa->is_flagged();
     $record->questionsummary = $qa->get_question_summary();
     if (core_text::strlen($record->questionsummary) > question_bank::MAX_SUMMARY_LENGTH) {
         // It seems some people write very long quesions! MDL-30760
         $record->questionsummary = core_text::substr($record->questionsummary, 0, question_bank::MAX_SUMMARY_LENGTH - 3) . '...';
     }
     $record->rightanswer = $qa->get_right_answer_summary();
     $record->responsesummary = $qa->get_response_summary();
     $record->timemodified = time();
     $record->id = $this->db->insert_record('question_attempts', $record);
     $qa->set_database_id($record->id);
     foreach ($qa->get_step_iterator() as $seq => $step) {
         $this->insert_question_attempt_step($step, $record->id, $seq, $context);
     }
 }
Exemple #29
0
    protected function num_parts_correct(question_attempt $qa) {
        if ($qa->get_question()->get_num_selected_choices($qa->get_last_qt_data()) >
                $qa->get_question()->get_num_correct_choices()) {
            return get_string('toomanyselected', 'qtype_multichoice');
        }

        return parent::num_parts_correct($qa);
    }
Exemple #30
0
 /**
  * Get the postdata that needs to be sent to question/toggleflag.php to change the flag state.
  * You need to append &newstate=0/1 to this.
  * @return the post data to send.
  */
 public static function get_postdata(question_attempt $qa)
 {
     $qaid = $qa->get_database_id();
     $qubaid = $qa->get_usage_id();
     $qid = $qa->get_question()->id;
     $slot = $qa->get_slot();
     $checksum = self::get_toggle_checksum($qubaid, $qid, $qaid, $slot);
     return "qaid={$qaid}&qubaid={$qubaid}&qid={$qid}&slot={$slot}&checksum={$checksum}&sesskey=" . sesskey() . '&newstate=';
 }