/** * Display the response analysis for a question. * @param object $question the question to report on. * @param int $s * @param moodle_url $reporturl the URL to redisplay this report. * @param qubaid_condition $qubaids */ protected function output_individual_question_response_analysis($question, $s, $reporturl, $qubaids) { global $OUTPUT; if (!question_bank::get_qtype($question->qtype, false)->can_analyse_responses()) { return; } $qtable = new quiz_statistics_question_table($question->id); $exportclass = $this->table->export_class_instance(); $qtable->export_class_instance($exportclass); if (!$this->table->is_downloading()) { // Output an appropriate title. echo $OUTPUT->heading(get_string('analysisofresponses', 'quiz_statistics'), 3); } else { // Work out an appropriate title. $questiontabletitle = '"' . $question->name . '"'; if (!empty($question->number)) { $questiontabletitle = '(' . $question->number . ') ' . $questiontabletitle; } if ($this->table->is_downloading() == 'xhtml') { $questiontabletitle = get_string('analysisofresponsesfor', 'quiz_statistics', $questiontabletitle); } // Set up the table. $exportclass->start_table($questiontabletitle); if ($this->table->is_downloading() == 'xhtml') { echo $this->render_question_text($question); } } $responesanalyser = new \core_question\statistics\responses\analyser($question); $responseanalysis = $responesanalyser->load_cached($qubaids); $qtable->question_setup($reporturl, $question, $s, $responseanalysis); if ($this->table->is_downloading()) { $exportclass->output_headers($qtable->headers); } foreach ($responseanalysis->get_subpart_ids() as $partid) { $subpart = $responseanalysis->get_subpart($partid); foreach ($subpart->get_response_class_ids() as $responseclassid) { $responseclass = $subpart->get_response_class($responseclassid); $tabledata = $responseclass->data_for_question_response_table($subpart->has_multiple_response_classes(), $partid); foreach ($tabledata as $row) { $qtable->add_data_keyed($qtable->format_row($row)); } } } $qtable->finish_output(!$this->table->is_downloading()); }
/** * Display the response analysis for a question. * * @param object $question the question to report on. * @param int|null $variantno the variant * @param int $s * @param moodle_url $reporturl the URL to redisplay this report. * @param qubaid_condition $qubaids * @param string $whichtries */ protected function output_individual_question_response_analysis($question, $variantno, $s, $reporturl, $qubaids, $whichtries = question_attempt::LAST_TRY) { global $OUTPUT; if (!question_bank::get_qtype($question->qtype, false)->can_analyse_responses()) { return; } $qtable = new quiz_statistics_question_table($question->id); $exportclass = $this->table->export_class_instance(); $qtable->export_class_instance($exportclass); if (!$this->table->is_downloading()) { // Output an appropriate title. echo $OUTPUT->heading(get_string('analysisofresponses', 'quiz_statistics'), 3); } else { // Work out an appropriate title. $a = clone $question; $a->variant = $variantno; if (!empty($question->number) && !is_null($variantno)) { $questiontabletitle = get_string('analysisnovariant', 'quiz_statistics', $a); } else { if (!empty($question->number)) { $questiontabletitle = get_string('analysisno', 'quiz_statistics', $a); } else { if (!is_null($variantno)) { $questiontabletitle = get_string('analysisvariant', 'quiz_statistics', $a); } else { $questiontabletitle = get_string('analysisnameonly', 'quiz_statistics', $a); } } } if ($this->table->is_downloading() == 'xhtml') { $questiontabletitle = get_string('analysisofresponsesfor', 'quiz_statistics', $questiontabletitle); } // Set up the table. $exportclass->start_table($questiontabletitle); if ($this->table->is_downloading() == 'xhtml') { echo $this->render_question_text($question); } } $responesanalyser = new \core_question\statistics\responses\analyser($question, $whichtries); $responseanalysis = $responesanalyser->load_cached($qubaids, $whichtries); $qtable->question_setup($reporturl, $question, $s, $responseanalysis); if ($this->table->is_downloading()) { $exportclass->output_headers($qtable->headers); } // Where no variant no is specified the variant no is actually one. if ($variantno === null) { $variantno = 1; } foreach ($responseanalysis->get_subpart_ids($variantno) as $partid) { $subpart = $responseanalysis->get_analysis_for_subpart($variantno, $partid); foreach ($subpart->get_response_class_ids() as $responseclassid) { $responseclass = $subpart->get_response_class($responseclassid); $tabledata = $responseclass->data_for_question_response_table($subpart->has_multiple_response_classes(), $partid); foreach ($tabledata as $row) { $qtable->add_data_keyed($qtable->format_row($row)); } } } $qtable->finish_output(!$this->table->is_downloading()); }
/** * @param $questions * @param $questionstats * @param $whichtries * @param $qubaids */ protected function check_variants_count_for_quiz_00($questions, $questionstats, $whichtries, $qubaids) { $expectedvariantcounts = array(2 => array(1 => 6, 4 => 4, 5 => 3, 6 => 4, 7 => 2, 8 => 5, 10 => 1)); foreach ($questions as $slot => $question) { if (!question_bank::get_qtype($question->qtype, false)->can_analyse_responses()) { continue; } $responesstats = new \core_question\statistics\responses\analyser($question); $this->assertTimeCurrent($responesstats->get_last_analysed_time($qubaids, $whichtries)); $analysis = $responesstats->load_cached($qubaids, $whichtries); $variantsnos = $analysis->get_variant_nos(); if (isset($expectedvariantcounts[$slot])) { // Compare contents, ignore ordering of array, using canonicalize parameter of assertEquals. $this->assertEquals(array_keys($expectedvariantcounts[$slot]), $variantsnos, '', 0, 10, true); } else { $this->assertEquals(array(1), $variantsnos); } $totalspervariantno = array(); foreach ($variantsnos as $variantno) { $subpartids = $analysis->get_subpart_ids($variantno); foreach ($subpartids as $subpartid) { if (!isset($totalspervariantno[$subpartid])) { $totalspervariantno[$subpartid] = array(); } $totalspervariantno[$subpartid][$variantno] = 0; $subpartanalysis = $analysis->get_analysis_for_subpart($variantno, $subpartid); $classids = $subpartanalysis->get_response_class_ids(); foreach ($classids as $classid) { $classanalysis = $subpartanalysis->get_response_class($classid); $actualresponsecounts = $classanalysis->data_for_question_response_table('', ''); foreach ($actualresponsecounts as $actualresponsecount) { $totalspervariantno[$subpartid][$variantno] += $actualresponsecount->totalcount; } } } } // Count all counted responses for each part of question and confirm that counted responses, for most question types // are the number of attempts at the question for each question part. if ($slot != 5) { // Slot 5 holds a multi-choice multiple question. // Multi-choice multiple is slightly strange. Actual answer counts given for each sub part do not add up to the // total attempt count. // This is because each option is counted as a sub part and each option can be off or on in each attempt. Off is // not counted in response analysis for this question type. foreach ($totalspervariantno as $totalpervariantno) { if (isset($expectedvariantcounts[$slot])) { // If we know how many attempts there are at each variant we can check // that we have counted the correct amount of responses for each variant. $this->assertEquals($expectedvariantcounts[$slot], $totalpervariantno, "Totals responses do not add up in response analysis for slot {$slot}.", 0, 10, true); } else { $this->assertEquals(25, array_sum($totalpervariantno), "Totals responses do not add up in response analysis for slot {$slot}."); } } } } foreach ($expectedvariantcounts as $slot => $expectedvariantcount) { foreach ($expectedvariantcount as $variantno => $s) { $this->assertEquals($s, $questionstats->for_slot($slot, $variantno)->s); } } }