/** * Analyse all the response data for for all the specified attempts at * this question. * @param $qubaids which attempts to consider. */ public function analyse($qubaids) { // Load data. $dm = new question_engine_data_mapper(); $questionattempts = $dm->load_attempts_at_question($this->questiondata->id, $qubaids); // Analyse it. foreach ($questionattempts as $qa) { $this->add_data_from_one_attempt($qa); } $this->loaded = true; }
/** * Display analysis of a particular question in this quiz. * @param object $question the row from the question table for the question to analyse. */ public function display_analysis($question) { get_question_options($question); $this->display_question_information($question); $dm = new question_engine_data_mapper(); $this->attempts = $dm->load_attempts_at_question($question->id, $this->qubaids); // Setup useful internal arrays for report generation. $this->inputs = array_keys($question->inputs); $this->prts = array_keys($question->prts); // TODO: change this to be a list of all *deployed* notes, not just those *used*. $qnotes = array(); foreach ($this->attempts as $qa) { $q = $qa->get_question(); $qnotes[$q->get_question_summary()] = true; } $this->qnotes = array_keys($qnotes); // Compute results. list($results, $answernoteresults, $answernoteresultsraw) = $this->input_report(); list($validresults, $invalidresults) = $this->input_report_separate(); // Display the results. // Overall results. $i = 0; $list = ''; $tablehead = array(); foreach ($this->qnotes as $qnote) { $list .= html_writer::tag('li', stack_ouput_castext($qnote)); $i++; $tablehead[] = $i; } $tablehead[] = format_string(get_string('questionreportingtotal', 'quiz_stack')); $tablehead = array_merge(array(''), $tablehead, $tablehead); echo html_writer::tag('p', get_string('notesused', 'quiz_stack')); echo html_writer::tag('ol', $list); // Complete anwernotes. $inputstable = new html_table(); $inputstable->head = $tablehead; $data = array(); foreach ($answernoteresults as $prt => $anotedata) { if (count($answernoteresults) > 1) { $inputstable->data[] = array(html_writer::tag('b', $this->prts[$prt])); } $cstats = $this->column_stats($anotedata); foreach ($anotedata as $anote => $a) { $inputstable->data[] = array_merge(array($anote), $a, array(array_sum($a)), $cstats[$anote]); } } echo html_writer::tag('p', get_string('completenotes', 'quiz_stack')); echo html_writer::table($inputstable); // Split anwernotes. $inputstable = new html_table(); $inputstable->head = $tablehead; foreach ($answernoteresultsraw as $prt => $anotedata) { if (count($answernoteresultsraw) > 1) { $inputstable->data[] = array(html_writer::tag('b', $this->prts[$prt])); } $cstats = $this->column_stats($anotedata); foreach ($anotedata as $anote => $a) { $inputstable->data[] = array_merge(array($anote), $a, array(array_sum($a)), $cstats[$anote]); } } echo html_writer::tag('p', get_string('splitnotes', 'quiz_stack')); echo html_writer::table($inputstable); // Maxima analysis. $maxheader = array(); $maxheader[] = "STACK input data for the question '" . $question->name . "'"; $maxheader[] = new moodle_url($this->get_base_url(), array('questionid' => $question->id)); $maxheader[] = "Data generated: " . date("Y-m-d H:i:s"); $maximacode = $this->maxima_comment($maxheader); $maximacode .= "\ndisplay2d:true\$\nload(\"stackreporting\")\$\n"; $maximacode .= "stackdata:[]\$\n"; $variants = array(); foreach ($this->qnotes as $qnote) { $variants[] = '"' . $qnote . '"'; } $inputs = array(); foreach ($this->inputs as $input) { $inputs[] = $input; } $anymaximadata = false; // Results for each question note. foreach ($this->qnotes as $qnote) { echo html_writer::tag('h2', get_string('variantx', 'quiz_stack') . stack_ouput_castext($qnote)); $inputstable = new html_table(); $inputstable->attributes['class'] = 'generaltable stacktestsuite'; $inputstable->head = array_merge(array(get_string('questionreportingsummary', 'quiz_stack'), '', get_string('questionreportingscore', 'quiz_stack')), $this->prts); foreach ($results[$qnote] as $dsummary => $summary) { foreach ($summary as $key => $res) { $inputstable->data[] = array_merge(array($dsummary, $res['count'], $res['fraction']), $res['answernotes']); } } echo html_writer::table($inputstable); // Separate out inputs and look at validity. $validresultsdata = array(); foreach ($this->inputs as $input) { $inputstable = new html_table(); $inputstable->attributes['class'] = 'generaltable stacktestsuite'; $inputstable->head = array($input, '', '', ''); foreach ($validresults[$qnote][$input] as $key => $res) { $validresultsdata[$input][] = $key; $inputstable->data[] = array($key, $res, get_string('inputstatusnamevalid', 'qtype_stack'), ''); $inputstable->rowclasses[] = 'pass'; } foreach ($invalidresults[$qnote][$input] as $key => $res) { $inputstable->data[] = array($key, $res[0], get_string('inputstatusnameinvalid', 'qtype_stack'), $res[1]); $inputstable->rowclasses[] = 'fail'; } echo html_writer::table($inputstable); } // Maxima analysis. $maximacode .= "\n/* " . $qnote . ' */ ' . "\n"; foreach ($this->inputs as $input) { if (array_key_exists($input, $validresultsdata)) { $maximacode .= $this->maxima_list_create($validresultsdata[$input], $input); $anymaximadata = true; } } $maximacode .= "stackdata:append(stackdata,[[" . implode(',', $inputs) . "]])\$\n"; } // Maxima analysis at the end. if ($anymaximadata) { $maximacode .= "\n/* Reset input names */\nkill(" . implode(',', $inputs) . ")\$\n"; $maximacode .= $this->maxima_list_create($variants, 'variants'); $maximacode .= $this->maxima_list_create($inputs, 'inputs'); $maximacode .= "\n/* Perform the analysis. */\nstack_analysis(stackdata)\$\n"; echo html_writer::tag('h3', get_string('maximacode', 'quiz_stack')); echo html_writer::tag('p', get_string('offlineanalysis', 'quiz_stack')); $rows = count(explode("\n", $maximacode)) + 2; echo html_writer::tag('textarea', $maximacode, array('readonly' => 'readonly', 'wrap' => 'virtual', 'rows' => $rows, 'cols' => '160')); } }
/** * Analyse all the response data for for all the specified attempts at this question. * * @param \qubaid_condition $qubaids which attempts to consider. * @param string $whichtries which tries to analyse. Will be one of * \question_attempt::FIRST_TRY, LAST_TRY or ALL_TRIES. * @return analysis_for_question */ public function calculate($qubaids, $whichtries = \question_attempt::LAST_TRY) { // Load data. $dm = new \question_engine_data_mapper(); $questionattempts = $dm->load_attempts_at_question($this->questiondata->id, $qubaids); // Analyse it. foreach ($questionattempts as $qa) { $responseparts = $qa->classify_response($whichtries); if ($this->breakdownbyvariant) { $this->analysis->count_response_parts($qa->get_variant(), $responseparts); } else { $this->analysis->count_response_parts(1, $responseparts); } } $this->analysis->cache($qubaids, $whichtries, $this->questiondata->id); return $this->analysis; }
/** * Analyse all the response data for for all the specified attempts at * this question. * @param \qubaid_condition $qubaids which attempts to consider. * @return analysis_for_question */ public function calculate($qubaids) { // Load data. $dm = new \question_engine_data_mapper(); $questionattempts = $dm->load_attempts_at_question($this->questiondata->id, $qubaids); // Analyse it. foreach ($questionattempts as $qa) { $responseparts = $qa->classify_response(); $this->analysis->count_response_parts($responseparts); } $this->analysis->cache($qubaids, $this->questiondata->id); return $this->analysis; }