Exemplo n.º 1
0
function hotpot_print_attempt_details(&$hotpot, &$attempt)
{
    // define fields to print
    $textfields = array('correct', 'ignored', 'wrong');
    $numfields = array('score', 'weighting', 'hints', 'clues', 'checks');
    $fields = array_merge($textfields, $numfields);
    $q = array();
    // questions
    $f = array();
    // fields
    foreach ($fields as $field) {
        $name = get_string($field, 'hotpot');
        $f[$field] = array('count' => 0, 'name' => $name);
    }
    // get questions and responses for this attempt
    $questions = get_records_select('hotpot_questions', "hotpot='{$hotpot->id}'", 'id');
    $responses = get_records_select('hotpot_responses', "attempt='{$attempt->id}'", 'id');
    if ($questions && $responses) {
        foreach ($responses as $response) {
            $id = $response->question;
            foreach ($fields as $field) {
                if (!isset($f[$field])) {
                    $name = get_string($field, 'hotpot');
                    $f[$field] = array('count' => 0, 'name' => $name);
                }
                if (isset($response->{$field})) {
                    $f[$field]['count']++;
                    if (!isset($q[$id])) {
                        $name = hotpot_get_question_name($questions[$id]);
                        $q[$id] = array('name' => $name);
                    }
                    $q[$id][$field] = $response->{$field};
                }
            }
        }
    }
    // count the number of columns required in the table
    $colspan = 0;
    foreach ($numfields as $field) {
        if ($f[$field]['count']) {
            $colspan += 2;
        }
    }
    $colspan = max(2, $colspan);
    // start table of questions and responses
    print_simple_box_start("center", "80%", "#ffffff", 0);
    print '<table width="100%" border="1" valign="top" align="center" cellpadding="2" cellspacing="2" class="generaltable">' . "\n";
    if (empty($q)) {
        print '<tr><td align="center" class="generaltablecell"><b>' . get_string("noresponses", "hotpot") . "</b></td></tr>\n";
    } else {
        // flag to ensure separators are only printed before the 2nd and subsequent questions
        $printseparator = false;
        foreach ($q as $i => $question) {
            // flag to ensure questions are only printed when there is at least one response
            $printedquestion = false;
            // add rows of text fields
            foreach ($textfields as $field) {
                if (isset($question[$field])) {
                    $text = hotpot_strings($question[$field]);
                    if (trim($text)) {
                        // print question if necessary
                        if (!$printedquestion) {
                            if ($printseparator) {
                                print '<tr><td colspan="' . $colspan . '"><div class="tabledivider"></div></td></tr>' . "\n";
                            }
                            $printseparator = true;
                            print '<tr><td colspan="' . $colspan . '" class="generaltablecell"><b>' . $question['name'] . '</b></td></tr>' . "\n";
                            $printedquestion = true;
                        }
                        // print response
                        print '<tr><th align="right" width="100" class="generaltableheader" scope="row">' . $f[$field]['name'] . ':</th><td colspan="' . ($colspan - 1) . '" class="generaltablecell">' . $text . '</td></tr>' . "\n";
                    }
                }
            }
            // add row of numeric fields
            print '<tr>';
            foreach ($numfields as $field) {
                if ($f[$field]['count']) {
                    // print question if necessary
                    if (!$printedquestion) {
                        print '<td colspan="' . $colspan . '" class="generaltablecell"><b>' . $question['name'] . "</b></td></tr>\n<tr>";
                        $printedquestion = true;
                    }
                    // print numeric response
                    $value = isset($question[$field]) ? $question[$field] : '-';
                    print '<th align="right" width="100" class="generaltableheader" scope="row">' . $f[$field]['name'] . ':</th><td class="generaltablecell">' . $value . '</td>';
                }
            }
            print "</tr>\n";
        }
        // foreach $q
    }
    // finish table
    print "</table>\n";
    print_simple_box_end();
}
Exemplo n.º 2
0
 function create_clickreport_table(&$hotpot, &$cm, &$course, &$users, &$attempts, &$questions, &$options, &$tables)
 {
     global $CFG;
     $is_html = $options['reportformat'] == 'htm';
     // time and date format strings		// date format strings
     $strftimetime = '%H:%M:%S';
     $strftimedate = get_string('strftimedate');
     // get the current time and max execution time
     $start_report_time = microtime();
     $max_execution_time = ini_get('max_execution_time');
     $correct = get_string('reportcorrectsymbol', 'hotpot');
     $wrong = get_string('reportwrongsymbol', 'hotpot');
     $nottried = get_string('reportnottriedsymbol', 'hotpot');
     // shortcuts for font tags
     $blank = $is_html ? '&nbsp;' : "";
     // store question count
     $questioncount = count($questions);
     // array to map columns onto question ids ($col => $id)
     $questionids = array_keys($questions);
     // store exercise type
     $exercisetype = $this->get_exercisetype($questions, $questionids, $blank);
     // initialize details ('events' must go last)
     $details = array('checks', 'status', 'answers', 'changes', 'hints', 'clues', 'events');
     // initialize $table
     unset($table);
     $table->border = 1;
     $table->width = '100%';
     // initialize legend, if necessary
     if (!empty($options['reportshowlegend'])) {
         $table->legend = array();
     }
     // start $table headings
     $this->set_head($options, $table, 'exercise');
     $this->set_head($options, $table, 'user');
     $this->set_head($options, $table, 'attempt');
     $this->set_head($options, $table, 'click');
     // store clicktype column number
     $clicktype_col = count($table->head) - 1;
     // finish $table headings
     $this->set_head($options, $table, 'details', $exercisetype, $details, $questioncount);
     $this->set_head($options, $table, 'totals', $exercisetype);
     // set align and wrap
     $this->set_align_and_wrap($table);
     // is link to review allowed?
     $allow_review = $is_html && (has_capability('mod/hotpot:viewreport', get_context_instance(CONTEXT_COURSE, $course->id)) || $hotpot->review);
     // initialize array of data values
     $this->data = array();
     // set exercise data values
     $this->set_data_exercise($cm, $course, $hotpot, $questions, $questionids, $questioncount, $blank);
     // add details of users' responses
     foreach ($users as $user) {
         $this->set_data_user($options, $course, $user);
         unset($clickreportid);
         foreach ($user->attempts as $attempt) {
             // initialize totals for
             $click = array('qnumber' => array(), 'correct' => array(), 'wrong' => array(), 'answers' => array(), 'hints' => array(), 'clues' => array(), 'changes' => array(), 'checks' => array(), 'events' => array(), 'score' => array(), 'weighting' => array());
             $clicktypes = array();
             // is the start of a new attempt?
             // (clicks in the same attempt have the same clickreportid)
             if (!isset($clickreportid) || $clickreportid != $attempt->clickreportid) {
                 $clickcount = 1;
                 $clickreportid = $attempt->clickreportid;
                 // initialize totals for all clicks in this attempt
                 $clicks = $click;
                 // $click has just been initialized
                 $this->set_data_attempt($attempt, $strftimedate, $strftimetime, $blank);
             }
             $cells = array();
             $this->set_data($cells, 'exercise');
             $this->set_data($cells, 'user');
             $this->set_data($cells, 'attempt');
             // get responses to questions in this attempt
             foreach ($attempt->responses as $response) {
                 // set $q(uestion number)
                 $q = array_search($response->question, $questionids);
                 $click['qnumber'][$q] = true;
                 // was this question answered correctly?
                 if ($answer = hotpot_strings($response->correct)) {
                     // mark the question as correctly answered
                     if (empty($clicks['correct'][$q])) {
                         $click['correct'][$q] = true;
                         $clicks['correct'][$q] = true;
                     }
                     // unset 'wrong' flags, if necessary
                     if (isset($click['wrong'][$q])) {
                         unset($click['wrong'][$q]);
                     }
                     if (isset($clicks['wrong'][$q])) {
                         unset($clicks['wrong'][$q]);
                     }
                     // otherwise, was the question answered wrongly?
                 } else {
                     if ($answer = hotpot_strings($response->wrong)) {
                         // mark the question as wrongly answered
                         $click['wrong'][$q] = true;
                         $clicks['wrong'][$q] = true;
                     } else {
                         // not correct or wrong (curious?!)
                         unset($answer);
                     }
                 }
                 if (!empty($click['correct'][$q]) || !empty($click['wrong'][$q])) {
                     $click['score'][$q] = $response->score;
                     $clicks['score'][$q] = $response->score;
                     $weighting = isset($response->weighting) ? $response->weighting : 100;
                     $click['weighting'][$q] = $weighting;
                     $clicks['weighting'][$q] = $weighting;
                 }
                 foreach ($details as $detail) {
                     switch ($detail) {
                         case 'answers':
                             if (isset($answer) && is_string($answer) && !empty($answer)) {
                                 $click[$detail][$q] = $answer;
                             }
                             break;
                         case 'hints':
                         case 'clues':
                         case 'checks':
                             if (isset($response->{$detail}) && is_numeric($response->{$detail}) && $response->{$detail} > 0) {
                                 if (!isset($click[$detail][$q]) || $click[$detail][$q] < $response->{$detail}) {
                                     $click[$detail][$q] = $response->{$detail};
                                 }
                             }
                             break;
                     }
                 }
                 // end foreach $detail
             }
             // end foreach $response
             $click['types'] = array();
             $this->data['details'] = array();
             foreach ($details as $detail) {
                 for ($q = 0; $q < $questioncount; $q++) {
                     switch ($detail) {
                         case 'status':
                             if (isset($clicks['correct'][$q])) {
                                 $this->data['details'][] = $correct;
                             } else {
                                 if (isset($clicks['wrong'][$q])) {
                                     $this->data['details'][] = $wrong;
                                 } else {
                                     if (isset($click['qnumber'][$q])) {
                                         $this->data['details'][] = $nottried;
                                     } else {
                                         // this question did not appear in this attempt
                                         $this->data['details'][] = $blank;
                                     }
                                 }
                             }
                             break;
                         case 'answers':
                         case 'hints':
                         case 'clues':
                         case 'checks':
                             if (!isset($clicks[$detail][$q])) {
                                 if (!isset($click[$detail][$q])) {
                                     $this->data['details'][] = $blank;
                                 } else {
                                     $clicks[$detail][$q] = $click[$detail][$q];
                                     if ($detail == 'answers') {
                                         $this->set_legend($table, $q, $click[$detail][$q], $questions[$questionids[$q]]);
                                     }
                                     $this->data['details'][] = $click[$detail][$q];
                                     $this->update_event_count($click, $detail, $q);
                                 }
                             } else {
                                 if (!isset($click[$detail][$q])) {
                                     $this->data['details'][] = $blank;
                                 } else {
                                     $difference = '';
                                     if ($detail == 'answers') {
                                         if ($click[$detail][$q] != $clicks[$detail][$q]) {
                                             $pattern = '/^' . preg_quote($clicks[$detail][$q], '/') . ',/';
                                             $difference = preg_replace($pattern, '', $click[$detail][$q], 1);
                                         }
                                     } else {
                                         // hints, clues, checks
                                         if ($click[$detail][$q] > $clicks[$detail][$q]) {
                                             $difference = $click[$detail][$q] - $clicks[$detail][$q];
                                         }
                                     }
                                     if ($difference) {
                                         $clicks[$detail][$q] = $click[$detail][$q];
                                         $click[$detail][$q] = $difference;
                                         if ($detail == 'answers') {
                                             $this->set_legend($table, $q, $difference, $questions[$questionids[$q]]);
                                         }
                                         $this->data['details'][] = $difference;
                                         $this->update_event_count($click, $detail, $q);
                                     } else {
                                         unset($click[$detail][$q]);
                                         $this->data['details'][] = $blank;
                                     }
                                 }
                             }
                             break;
                         case 'changes':
                         case 'events':
                             if (empty($click[$detail][$q])) {
                                 $this->data['details'][] = $blank;
                             } else {
                                 $this->data['details'][] = $click[$detail][$q];
                             }
                             break;
                         default:
                             // do nothing
                             break;
                     }
                     // end switch
                 }
                 // for $q
             }
             // foreach $detail
             // set data cell values for
             $this->set_data_click($allow_review ? '<a href="review.php?hp=' . $hotpot->id . '&amp;attempt=' . $attempt->id . '">' . $clickcount . '</a>' : $clickcount, trim(userdate($attempt->timefinish, $strftimetime)), $exercisetype, $click);
             $this->set_data($cells, 'click');
             $this->set_data($cells, 'details');
             $this->set_data_totals($click, $clicks, $questioncount, $blank, $attempt);
             $this->set_data($cells, 'totals');
             $table->data[] = $cells;
             $clickcount++;
         }
         // end foreach $attempt
         // insert 'tabledivider' between users
         $table->data[] = 'hr';
     }
     // end foreach $user
     // remove final 'hr' from data rows
     array_pop($table->data);
     if ($is_html && $CFG->hotpot_showtimes) {
         $count = count($users);
         $duration = sprintf("%0.3f", microtime_diff($start_report_time, microtime()));
         print "{$count} users processed in {$duration} seconds (" . sprintf("%0.3f", $duration / $count) . ' secs/user)<hr size="1" noshade="noshade" />' . "\n";
     }
     $tables[] =& $table;
     $this->create_legend_table($tables, $table);
 }
Exemplo n.º 3
0
 function create_responses_table(&$hotpot, &$course, &$users, &$attempts, &$questions, &$options, &$tables)
 {
     global $CFG;
     $is_html = $options['reportformat'] == 'htm';
     // shortcuts for font tags
     $br = $is_html ? "<br />\n" : "\n";
     $blank = $is_html ? '&nbsp;' : "";
     $font_end = $is_html ? '</font>' : '';
     $font_red = $is_html ? '<font color="red">' : '';
     $font_blue = $is_html ? '<font color="blue">' : '';
     $font_brown = $is_html ? '<font color="brown">' : '';
     $font_green = $is_html ? '<font color="green">' : '';
     $font_small = $is_html ? '<font size="-2">' : '';
     $nobr_start = $is_html ? '<nobr>' : '';
     $nobr_end = $is_html ? '</nobr>' : '';
     // is review allowed? (do this once here, to save time later)
     $allow_review = $is_html && (has_capability('mod/hotpot:viewreport', get_context_instance(CONTEXT_COURSE, $course->id)) || $hotpot->review);
     // assume penalties column is NOT required
     $show_penalties = false;
     // initialize $table
     unset($table);
     $table->border = 1;
     $table->width = '100%';
     // initialize legend, if necessary
     if (!empty($options['reportshowlegend'])) {
         $table->legend = array();
     }
     // headings for name, attempt number, score/grade and penalties
     $table->head = array(get_string("name"), hotpot_grade_heading($hotpot, $options), get_string('attempt', 'quiz'));
     $table->align = array('left', 'center', 'center');
     $table->size = array(150, 80, 10);
     $table->wrap = array(0, 0, 0);
     $table->fontsize = array(0, 0, 0);
     // question headings
     $this->add_question_headings($questions, $table, 'left', 0, false, 2);
     // penalties (not always needed) and raw score
     array_push($table->head, get_string('penalties', 'hotpot'), get_string('score', 'quiz'));
     array_push($table->align, 'center', 'center');
     array_push($table->size, 50, 50);
     array_push($table->wrap, 0, 0);
     array_push($table->fontsize, 0, 0);
     // message strings
     $strnoresponse = get_string('noresponse', 'quiz');
     // array to map columns onto question ids ($col => $id)
     $questionids = array_keys($questions);
     // add details of users' responses
     foreach ($users as $user) {
         // shortcut to user info held in first attempt record
         $u =& $user->attempts[0];
         if (function_exists("fullname")) {
             $name = fullname($u);
         } else {
             $name = "{$u->firstname} {$u->lastname}";
         }
         if ($is_html) {
             $name = '<a href="' . $CFG->wwwroot . '/user/view.php?id=' . $u->userid . '&amp;course=' . $course->id . '">' . $name . '</a>';
         }
         $grade = isset($user->grade) ? $user->grade : $blank;
         foreach ($user->attempts as $attempt) {
             $attemptnumber = $attempt->attempt;
             if ($allow_review) {
                 $attemptnumber = ' <a href="review.php?hp=' . $hotpot->id . '&amp;attempt=' . $attempt->id . '">' . $attemptnumber . '</a>';
             }
             $cells = array($name, $grade, $attemptnumber);
             // $name and $grade are only printed on first line per user
             $name = $blank;
             $grade = $blank;
             $start_col = count($cells);
             foreach ($questionids as $col => $id) {
                 $cells[$start_col + $col] = "{$font_brown}({$strnoresponse}){$font_end}";
             }
             if (isset($attempt->penalties)) {
                 $show_penalties = true;
                 $penalties = $attempt->penalties;
             } else {
                 $penalties = $blank;
             }
             array_push($cells, $penalties, hotpot_format_score($attempt));
             // get responses to questions in this attempt
             foreach ($attempt->responses as $response) {
                 // check this question id is OK (should be)
                 $col = array_search($response->question, $questionids);
                 if (is_numeric($col)) {
                     // correct
                     if ($value = hotpot_strings($response->correct)) {
                         $this->set_legend($table, $col, $value, $questions[$response->question]);
                     } else {
                         $value = "({$strnoresponse})";
                     }
                     $cell = $font_red . $value . $font_end;
                     // wrong
                     if ($value = hotpot_strings($response->wrong)) {
                         if (isset($table->legend)) {
                             $values = array();
                             foreach (explode(',', $value) as $v) {
                                 $this->set_legend($table, $col, $v, $questions[$response->question]);
                                 $values[] = $v;
                             }
                             $value = implode(',', $values);
                         }
                         $cell .= $br . $font_blue . $value . $font_end;
                     }
                     // ignored
                     if ($value = hotpot_strings($response->ignored)) {
                         if (isset($table->legend)) {
                             $values = array();
                             foreach (explode(',', $value) as $v) {
                                 $this->set_legend($table, $col, $v, $questions[$response->question]);
                                 $values[] = $v;
                             }
                             $value = implode(',', $values);
                         }
                         $cell .= $br . $font_brown . $value . $font_end;
                     }
                     // numeric
                     if (is_numeric($response->score)) {
                         if (empty($table->caption)) {
                             $table->caption = get_string('indivresp', 'quiz');
                             if ($is_html) {
                                 $table->caption .= helpbutton('responsestable', $table->caption, 'hotpot', true, false, '', true);
                             }
                         }
                         $hints = empty($response->hints) ? 0 : $response->hints;
                         $clues = empty($response->clues) ? 0 : $response->clues;
                         $checks = empty($response->checks) ? 0 : $response->checks;
                         $numeric = $response->score . '% ' . $blank . ' (' . $hints . ',' . $clues . ',' . $checks . ')';
                         $cell .= $br . $nobr_start . $font_green . $numeric . $font_end . $nobr_end;
                     }
                     $cells[$start_col + $col] = $cell;
                 }
             }
             $table->data[] = $cells;
         }
         // insert 'tabledivider' between users
         $table->data[] = 'hr';
     }
     // end foreach $users
     // remove final 'hr' from data rows
     array_pop($table->data);
     if (!$show_penalties) {
         $col = 3 + count($questionids);
         $this->remove_column($table, $col);
     }
     $tables[] =& $table;
 }
Exemplo n.º 4
0
function hotpot_get_question_name($question)
{
    $name = '';
    if (isset($question->text)) {
        $name = hotpot_strings($question->text);
    }
    if (empty($name)) {
        $name = $question->name;
    }
    return $name;
}
Exemplo n.º 5
0
function hotpot_set_attempt_details(&$attempt)
{
    global $CFG, $HOTPOT_QUIZTYPE;
    // optional_param('showallquestions', 0, PARAM_INT);
    $attempt->details = '';
    $attempt->score = 0;
    $attempt->status = HOTPOT_STATUS_COMPLETED;
    $buttons = array('clues', 'hints', 'checks');
    $textfields = array('correct', 'wrong', 'ignored');
    $ok = false;
    $quiztype = optional_param('quiztype', 0, PARAM_ALPHANUM);
    if ($quiztype) {
        if (is_numeric($quiztype)) {
            $ok = array_key_exists($quiztype, $HOTPOT_QUIZTYPE);
        } else {
            $quiztype = array_search($quiztype, $HOTPOT_QUIZTYPE);
            $ok = is_numeric($quiztype);
        }
    }
    if (!$ok) {
        return;
        // error('Quiz type is missing or invalid');
        // print_error('error_invalidquiztype', 'hotpot');
        //
        // script finishes here if quiztype is invalid
        //
    }
    // special flag to detect jquiz multiselect
    $is_jquiz_multiselect = false;
    // set maximum question number
    $q_max = 0;
    do {
        switch ($quiztype) {
            case HOTPOT_JCLOZE:
            case HOTPOT_JQUIZ:
                $field = "q{$q_max}_a0_text";
                break;
            case HOTPOT_JCB:
            case HOTPOT_JCROSS:
            case HOTPOT_JMATCH:
            case HOTPOT_JMIX:
            default:
                $field = '';
        }
    } while ($field && isset($_POST[$field]) && ($q_max = $q_max + 1));
    // check JQuiz navigation buttons
    switch (true) {
        case isset($_POST['ShowAllQuestionsButton']):
            $_POST['ShowAllQuestions'] = 1;
            break;
        case isset($_POST['ShowOneByOneButton']):
            $_POST['ShowAllQuestions'] = 0;
            break;
        case isset($_POST['PrevQButton']):
            $_POST['ThisQuestion']--;
            break;
        case isset($_POST['NextQButton']):
            $_POST['ThisQuestion']++;
            break;
    }
    $q = 0;
    while ($q < $q_max) {
        $responsefield = "q{$q}";
        $questiontype = optional_param("{$responsefield}_questiontype", 0, PARAM_INT);
        $is_jquiz_multiselect = $quiztype == HOTPOT_JQUIZ && $questiontype == HOTPOT_JQUIZ_MULTISELECT;
        if (isset($_POST[$responsefield]) && is_array($_POST[$responsefield])) {
            $responsevalue = array();
            foreach ($_POST[$responsefield] as $key => $value) {
                $responsevalue[$key] = clean_param($value, PARAM_CLEAN);
            }
        } else {
            $responsevalue = optional_param($responsefield, '');
        }
        if (is_array($responsevalue)) {
            // incomplete jquiz multi-select
            $responsevalues = $responsevalue;
            $responsevalue = implode('+', $responsevalue);
        } else {
            $responsevalues = explode('+', $responsevalue);
        }
        // initialize $response object
        $response = new stdClass();
        $response->correct = array();
        $response->wrong = array();
        $response->ignored = array();
        $response->clues = 0;
        $response->hints = 0;
        $response->checks = 0;
        $response->score = 0;
        $response->weighting = 0;
        // create another empty object to hold all previous responses (from database)
        $oldresponse = new stdClass();
        $vars = get_object_vars($response);
        foreach ($vars as $name => $value) {
            $oldresponse->{$name} = $value;
        }
        foreach ($buttons as $button) {
            if (($field = "q{$q}_{$button}_button") && isset($_POST[$field])) {
                $value = optional_param($field, '', PARAM_RAW);
                if (!empty($value)) {
                    $response->{$button}++;
                }
            }
        }
        // loop through possible answers to this question
        $firstcorrectvalue = '';
        $percents = array();
        $a = 0;
        while (($valuefield = "q{$q}_a{$a}_text") && isset($_POST[$valuefield])) {
            $value = optional_param($valuefield, '', PARAM_RAW);
            if (($percentfield = "q{$q}_a{$a}_percent") && isset($_POST[$percentfield])) {
                $percent = optional_param($percentfield, 0, PARAM_INT);
                if ($percent) {
                    $percents[$value] = $percent;
                }
            }
            if (($correctfield = "q{$q}_a{$a}_correct") && isset($_POST[$correctfield])) {
                $correct = optional_param($correctfield, 0, PARAM_INT);
            } else {
                $correct = false;
            }
            if ($correct && empty($firstcorrectvalue)) {
                $firstcorrectvalue = $value;
            }
            if ($is_jquiz_multiselect) {
                $selected = in_array($value, $responsevalues);
                if ($correct) {
                    $response->correct[] = $value;
                    if (empty($selected)) {
                        $response->wrong[] = true;
                    }
                } else {
                    if ($selected) {
                        $response->wrong[] = true;
                    }
                }
            } else {
                // single answer only required
                if ($responsevalue == $value) {
                    if ($correct) {
                        $response->correct[] = $value;
                    } else {
                        $response->wrong[] = $value;
                    }
                } else {
                    $response->ignored[] = $value;
                }
            }
            $a++;
        }
        // number of answers for this question
        $a_max = $a;
        if ($is_jquiz_multiselect) {
            if (empty($response->wrong) && count($responsevalues) == count($response->correct)) {
                $response->wrong = array();
                $response->correct = array($responsevalue);
            } else {
                $response->correct = array();
                $response->wrong = array($responsevalue);
            }
        } else {
            // if response did not match any answer, then this response is wrong
            if (empty($response->correct) && empty($response->wrong)) {
                $response->wrong[] = $responsevalue;
            }
        }
        // if this question has not been answered correctly, quiz is still in progress
        if (empty($response->correct)) {
            if (isset($_POST["q{$q}_ShowAnswers_button"])) {
                $_POST[$responsefield] = $firstcorrectvalue;
            } else {
                $attempt->status = HOTPOT_STATUS_INPROGRESS;
                if (isset($_POST["q{$q}_Hint_button"])) {
                    // a particular hint button in JQuiz shortanswer
                    $_POST['HintButton'] = true;
                }
                // give a hint, if necessary
                if (isset($_POST['HintButton']) && $firstcorrectvalue) {
                    // make sure we only come through here once
                    unset($_POST['HintButton']);
                    $correctlen = strlen($firstcorrectvalue);
                    $responselen = strlen($responsevalue);
                    // check how many letters are the same
                    $i = 0;
                    while ($i < $responselen && $i < $correctlen && $responsevalue[$i] == $firstcorrectvalue[$i]) {
                        $i++;
                    }
                    if ($i < $responselen) {
                        // remove incorrect characters on the end of the response
                        $responsevalue = substr($responsevalue, 0, $i);
                    }
                    if ($i < $correctlen) {
                        // append next correct letter
                        $responsevalue .= $firstcorrectvalue[$i];
                    }
                    $_POST[$responsefield] = $responsevalue;
                    $response->hints++;
                }
                // end if hint
            }
        }
        // end if not correct
        // get clue text, if any
        if (($field = "q{$q}_clue") && isset($_POST[$field])) {
            $response->clue_text = optional_param($field, '', PARAM_RAW);
        }
        // get question name
        $qq = sprintf('%02d', $q);
        // (a padded, two-digit version of $q)
        if (($field = "q{$q}_name") && isset($_POST[$field])) {
            $questionname = optional_param($field, '', PARAM_RAW);
            $questionname = strip_tags($questionname);
        } else {
            $questionname = $qq;
        }
        // get previous responses to this question (if any)
        $records = get_records_sql("\n            SELECT\n                r.*\n            FROM\n                {$CFG->prefix}hotpot_attempts a,\n                {$CFG->prefix}hotpot_questions q,\n                {$CFG->prefix}hotpot_responses r\n            WHERE\n                a.clickreportid = {$attempt->clickreportid} AND\n                a.id = r.attempt AND\n                r.question = q.id AND\n                q.name = '{$questionname}' AND\n                q.hotpot = {$attempt->hotpot}\n            ORDER BY\n                a.timefinish\n        ");
        if ($records) {
            foreach ($records as $record) {
                foreach ($buttons as $button) {
                    $oldresponse->{$button} = max($oldresponse->{$button}, $record->{$button});
                }
                foreach ($textfields as $field) {
                    if ($record->{$field} && ($field == 'correct' || $field == 'wrong')) {
                        $values = explode(',', hotpot_strings($record->{$field}));
                        $oldresponse->{$field} = array_merge($oldresponse->{$field}, $values);
                    }
                }
            }
        }
        // remove "correct" and "wrong" values from "ignored" values
        $response->ignored = array_diff($response->ignored, $response->correct, $response->wrong, $oldresponse->correct, $oldresponse->wrong);
        foreach ($buttons as $button) {
            $response->{$button} += $oldresponse->{$button};
        }
        $value_has_changed = false;
        foreach ($textfields as $field) {
            $response->{$field} = array_merge($oldresponse->{$field}, $response->{$field});
            $response->{$field} = array_unique($response->{$field});
            $response->{$field} = implode(',', $response->{$field});
            if ($field == 'correct' || $field == 'wrong') {
                $array = $oldresponse->{$field};
                $array = array_unique($array);
                $oldresponse->{$field} = implode(',', $array);
                if ($response->{$field} != $oldresponse->{$field}) {
                    $value_has_changed = true;
                }
            }
        }
        if ($value_has_changed) {
            $response->checks++;
        }
        // $response now holds amalgamation of all responses so far to this question
        // set question score and weighting
        if ($response->correct) {
            switch ($quiztype) {
                case HOTPOT_JCB:
                    break;
                case HOTPOT_JCLOZE:
                    $strlen = strlen($response->correct);
                    $response->score = 100 * ($strlen - ($response->checks - 1)) / $strlen;
                    $attempt->score += $response->score;
                    break;
                case HOTPOT_JCROSS:
                    break;
                case HOTPOT_JMATCH:
                    break;
                case HOTPOT_JMIX:
                    break;
                case HOTPOT_JQUIZ:
                    switch ($questiontype) {
                        case HOTPOT_JQUIZ_MULTICHOICE:
                            $wrong = explode(',', $response->wrong);
                            foreach ($wrong as $value) {
                                if (isset($percents[$value])) {
                                    $percent = $percents[$value];
                                } else {
                                    $percent = 0;
                                }
                            }
                        case HOTPOT_JQUIZ_SHORTANSWER:
                            $strlen = strlen($response->correct);
                            $response->score = 100 * ($strlen - ($response->checks - 1)) / $strlen;
                            break;
                        case HOTPOT_JQUIZ_MULTISELECT:
                            if (isset($percents[$response->correct])) {
                                $percent = $percents[$response->correct];
                            } else {
                                $percent = 0;
                            }
                            if ($a_max > 0 && $response->checks > 0 && $a_max > $response->checks) {
                                $response->score = $percent * ($a_max - ($response->checks - 1)) / $a_max;
                            }
                            break;
                    }
                    $attempt->score += $response->score;
                    break;
            }
        }
        $fieldname = $HOTPOT_QUIZTYPE[$quiztype] . "_q{$qq}_name";
        $attempt->details .= "<field><fieldname>{$fieldname}</fieldname><fielddata>{$questionname}</fielddata></field>";
        // encode $response fields as XML
        $vars = get_object_vars($response);
        foreach ($vars as $name => $value) {
            if (!empty($value)) {
                $fieldname = $HOTPOT_QUIZTYPE[$quiztype] . "_q{$qq}_{$name}";
                $attempt->details .= "<field><fieldname>{$fieldname}</fieldname><fielddata>{$value}</fielddata></field>";
            }
        }
        $q++;
    }
    // end main loop through $q(uestions)
    // set attempt score
    if ($q > 0) {
        switch ($quiztype) {
            case HOTPOT_JCB:
                break;
            case HOTPOT_JCLOZE:
                $attempt->score = floor($attempt->score / $q);
                break;
            case HOTPOT_JCROSS:
                break;
            case HOTPOT_JMATCH:
                break;
            case HOTPOT_JMIX:
                break;
            case HOTPOT_JQUIZ:
                break;
        }
    }
    if ($attempt->details) {
        $attempt->details = '<?xml version="1.0"?><hpjsresult><fields>' . $attempt->details . '</fields></hpjsresult>';
    }
    //  print "forcing status to in progress ..<br/>\n";
    //  $attempt->status = HOTPOT_STATUS_INPROGRESS;
}