New version of item analysis from Enrique

This commit is contained in:
gustav_delius 2005-05-23 07:25:33 +00:00
parent cf74468046
commit a472ce5960
9 changed files with 243 additions and 119 deletions

View file

@ -377,14 +377,18 @@ class quiz_default_questiontype {
* for the question * for the question
* *
* All answers are found and their text values isolated * All answers are found and their text values isolated
* @return array An array of values giving the responses corresponding * @return object A mixed object
* to all answers to the question. Answer ids are used as keys * ->id question id. Needed to manage random questions:
* it's the id of the actual question presented to user in a given attempt
* ->responses An array of values giving the responses corresponding
* to all answers to the question. Answer ids are used as keys.
* The text and partial credit are the object components
* @param object $question The question for which the answers are to * @param object $question The question for which the answers are to
* be retrieved. Question type specific information is * be retrieved. Question type specific information is
* available. * available.
*/ */
// ULPGC ecastro // ULPGC ecastro
function get_all_responses($question, $state) { function get_all_responses(&$question, &$state) {
unset($answers); unset($answers);
if (is_array($question->options->answers)) { if (is_array($question->options->answers)) {
foreach ($question->options->answers as $aid=>$answer) { foreach ($question->options->answers as $aid=>$answer) {
@ -405,8 +409,8 @@ class quiz_default_questiontype {
* Return the actual response to the question in a given state * Return the actual response to the question in a given state
* for the question * for the question
* *
* @return compond object fractiongrade & actual response . * @return mixed An array containing the response or reponses (multiple answer, match)
* * given by the user in a particular attempt.
* @param object $question The question for which the correct answer is to * @param object $question The question for which the correct answer is to
* be retrieved. Question type specific information is * be retrieved. Question type specific information is
* available. * available.
@ -415,7 +419,7 @@ class quiz_default_questiontype {
* type specific information is included. * type specific information is included.
*/ */
// ULPGC ecastro // ULPGC ecastro
function get_actual_response($question, $state) { function get_actual_response(&$question, &$state) {
/* The default implementation only returns the raw ->responses. /* The default implementation only returns the raw ->responses.
may be overridden by each type*/ may be overridden by each type*/
//unset($resp); //unset($resp);
@ -427,7 +431,7 @@ class quiz_default_questiontype {
} }
// ULPGC ecastro // ULPGC ecastro
function get_fractional_grade($question, $state) { function get_fractional_grade(&$question, &$state) {
$maxgrade = $question->maxgrade; $maxgrade = $question->maxgrade;
$grade = $state->grade; $grade = $state->grade;
if ($maxgrade) { if ($maxgrade) {
@ -437,6 +441,24 @@ class quiz_default_questiontype {
} }
} }
/**
* Checks if the response given is correct and returns the id
*
* @return int The ide number for the stored answer that matches the response
* given by the user in a particular attempt.
* @param object $question The question for which the correct answer is to
* be retrieved. Question type specific information is
* available.
* @param object $state The state object that corresponds to the question,
* for which a correct answer is needed. Question
* type specific information is included.
*/
// ULPGC ecastro
function check_response(&$question, &$state){
return false;
}
/** /**
* Prints the question including the number, grading details, content, * Prints the question including the number, grading details, content,
* feedback and interactions * feedback and interactions
@ -1776,6 +1798,7 @@ function quiz_print_question_icon($question, $editlink=true, $return = false) {
function quiz_get_question_review($quiz, $question) { function quiz_get_question_review($quiz, $question) {
// returns a question icon // returns a question icon
$qnum = $question->id; $qnum = $question->id;
$strpreview = get_string('previewquestion', 'quiz');
$context = $quiz->id ? '&contextquiz='.$quiz->id : ''; $context = $quiz->id ? '&contextquiz='.$quiz->id : '';
$quiz_id = $quiz->id ? '&quizid=' . $quiz->id : ''; $quiz_id = $quiz->id ? '&quizid=' . $quiz->id : '';
return "<a title=\"$strpreview\" href=\"javascript:void();\" onClick=\"openpopup('/mod/quiz/preview.php?id=$qnum$quiz_id','$strpreview','scrollbars=yes,resizable=yes,width=700,height=480', false)\"> return "<a title=\"$strpreview\" href=\"javascript:void();\" onClick=\"openpopup('/mod/quiz/preview.php?id=$qnum$quiz_id','$strpreview','scrollbars=yes,resizable=yes,width=700,height=480', false)\">

View file

@ -7,6 +7,7 @@
/// QUESTION TYPE CLASS ////////////////// /// QUESTION TYPE CLASS //////////////////
require_once("$CFG->dirroot/mod/quiz/questiontypes/datasetdependent/abstractqtype.php"); require_once("$CFG->dirroot/mod/quiz/questiontypes/datasetdependent/abstractqtype.php");
class quiz_calculated_qtype extends quiz_dataset_dependent_questiontype { class quiz_calculated_qtype extends quiz_dataset_dependent_questiontype {
// Used by the function custom_generator_tools: // Used by the function custom_generator_tools:
@ -153,6 +154,49 @@ class quiz_calculated_qtype extends quiz_dataset_dependent_questiontype {
} }
return parent::grade_responses($question, $state, $quiz); return parent::grade_responses($question, $state, $quiz);
} }
// ULPGC ecastro
function check_response(&$question, &$state) {
// Forward the checking to the virtual qtype
foreach ($question->options->answers as $key => $answer) {
$answer = &$question->options->answers[$key]; // for PHP 4.x
$answer->answer = $this->substitute_variables($answer->answer,
$state->options->dataset);
}
//return false;
return parent::check_response($question, $state);
}
// ULPGC ecastro
function get_actual_response(&$question, &$state) {
// Substitute variables in questiontext before giving the data to the
// virtual type
$virtualqtype = $this->get_virtual_qtype();
$unit = $virtualqtype->get_default_numerical_unit($question);
foreach ($question->options->answers as $key => $answer) {
$answer = &$question->options->answers[$key]; // for PHP 4.x
$answer->answer = $this->substitute_variables($answer->answer,
$state->options->dataset);
// apply_unit
}
$question->questiontext = parent::substitute_variables(
$question->questiontext, $state->options->dataset);
$responses = $virtualqtype->get_all_responses($question, $state);
$response = reset($responses->responses);
$correct = $response->answer.' : ';
$responses = $virtualqtype->get_actual_response($question, $state);
foreach ($responses as $key=>$response){
$responses[$key] = $correct.$response;
}
return $responses;
}
function create_virtual_qtype() { function create_virtual_qtype() {
global $CFG; global $CFG;
@ -419,6 +463,10 @@ class quiz_calculated_qtype extends quiz_dataset_dependent_questiontype {
return null; return null;
} }
function substitute_variables($str, $dataset) { function substitute_variables($str, $dataset) {
$formula = parent::substitute_variables($str, $dataset); $formula = parent::substitute_variables($str, $dataset);
if ($error = quiz_qtype_calculated_find_formula_errors($formula)) { if ($error = quiz_qtype_calculated_find_formula_errors($formula)) {

View file

@ -113,6 +113,20 @@ class quiz_dataset_dependent_questiontype extends quiz_default_questiontype {
$virtualqtype = $this->get_virtual_qtype(); $virtualqtype = $this->get_virtual_qtype();
return $virtualqtype->grade_responses($question, $state, $quiz) ; return $virtualqtype->grade_responses($question, $state, $quiz) ;
} }
// ULPGC ecastro
function check_response(&$question, &$state) {
// Forward the checking to the virtual qtype
foreach ($question->options->answers as $answer) {
$answer->answer = $this->substitute_variables($answer->answer,
$state->options->dataset);
}
$virtualqtype = $this->get_virtual_qtype();
return $virtualqtype->check_response($question, $state) ;
}
function substitute_variables($str, $dataset) { function substitute_variables($str, $dataset) {
foreach ($dataset as $name => $value) { foreach ($dataset as $name => $value) {

View file

@ -351,22 +351,13 @@ class quiz_multichoice_qtype extends quiz_default_questiontype {
// ULPGC ecastro // ULPGC ecastro
function get_actual_response($question, $state) { function get_actual_response($question, $state) {
$answers = $question->options->answers; $answers = $question->options->answers;
/* if (!empty($state->responses)) {
if (!$question->options->single) { foreach ($state->responses as $aid =>$rid){
echo "Objeto State-responses: <br>tamaño= ".count($state->responses)."<br> "; $answer = $answers[$rid]->answer;
print_object($state->responses); $responses[] = $answer;
foreach ($state->responses as $resp){ }
echo "esto es response id= ".$rid." <br>"; } else {
print_object($resp); $responses[] = '';
echo " Tamaño interno=".count($resp);
foreach ($resp as $r){
print_object($r);
}
}
}*/
foreach ($state->responses as $rid){
$answer = $answers[$rid]->answer;
$responses[] = $answer;
} }
return $responses; return $responses;
} }

View file

@ -229,6 +229,17 @@ class quiz_numerical_qtype extends quiz_shortanswer_qtype {
return ($response == $answer->answer); return ($response == $answer->answer);
} }
} }
// ULPGC ecastro
function check_response(&$question, &$state){
$answers = &$question->options->answers;
foreach($answers as $aid => $answer) {
if($this->test_response($question, $state, $answer)) {
return $aid;
}
}
return false;
}
function print_question_formulation_and_controls(&$question, &$state, $quiz, $options) { function print_question_formulation_and_controls(&$question, &$state, $quiz, $options) {
/// This implementation is very similar to the code used by question type SHORTANSWER /// This implementation is very similar to the code used by question type SHORTANSWER
@ -308,6 +319,34 @@ class quiz_numerical_qtype extends quiz_shortanswer_qtype {
return $correct; return $correct;
} }
// ULPGC ecastro
function get_all_responses(&$question, &$state) {
unset($answers);
$unit = $this->get_default_numerical_unit($question);
if (is_array($question->options->answers)) {
foreach ($question->options->answers as $aid=>$answer) {
unset ($r);
$r->answer = $answer->answer;
$r->credit = $answer->fraction;
$this->get_tolerance_interval($answer);
if ($unit) {
$r->answer .= ' '.$unit->unit;
}
if ($answer->max != $answer->min) {
$max = "$answer->max"; //format_float($answer->max, 2);
$min = "$answer->min"; //format_float($answer->max, 2);
$r->answer .= ' ('.$min.'..'.$max.')';
}
$answers[$aid] = $r;
}
} else {
$answers[]="error"; // just for debugging, eliminate
}
$result->id = $question->id;
$result->responses = $answers;
return $result;
}
function get_tolerance_interval(&$answer) { function get_tolerance_interval(&$answer) {
// No tolerance // No tolerance
if (empty($answer->tolerance)) { if (empty($answer->tolerance)) {

View file

@ -171,7 +171,7 @@ class quiz_random_qtype extends quiz_default_questiontype {
} }
// ULPGC ecastro // ULPGC ecastro
function get_all_responses($question, $state){ function get_all_responses(&$question, &$state){
global $QUIZ_QTYPES; global $QUIZ_QTYPES;
$wrappedquestion = &$state->options->question; $wrappedquestion = &$state->options->question;
return $QUIZ_QTYPES[$wrappedquestion->qtype] return $QUIZ_QTYPES[$wrappedquestion->qtype]
@ -179,7 +179,7 @@ class quiz_random_qtype extends quiz_default_questiontype {
} }
// ULPGC ecastro // ULPGC ecastro
function get_actual_response($question, $state){ function get_actual_response(&$question, &$state){
global $QUIZ_QTYPES; global $QUIZ_QTYPES;
$wrappedquestion = &$state->options->question; $wrappedquestion = &$state->options->question;
return $QUIZ_QTYPES[$wrappedquestion->qtype] return $QUIZ_QTYPES[$wrappedquestion->qtype]

View file

@ -150,6 +150,20 @@ class quiz_shortanswer_qtype extends quiz_default_questiontype {
} }
} }
// ULPGC ecastro
function check_response(&$question, &$state) {
$answers = &$question->options->answers;
$testedstate = clone($state);
$teststate = clone($state);
foreach($answers as $aid => $answer) {
$teststate->responses[''] = trim($answer->answer);
if($this->compare_responses($question, $testedstate, $teststate)) {
return $aid;
}
}
return false;
}
function grade_responses(&$question, &$state, $quiz) { function grade_responses(&$question, &$state, $quiz) {
$answers = &$question->options->answers; $answers = &$question->options->answers;
$testedstate = clone($state); $testedstate = clone($state);

View file

@ -1,28 +1,8 @@
<?php // $Id$ <?php // $Id$
/// Item analysis displays a table of quiz questions and their performance /// Item analysis displays a table of quiz questions and their performance
require_once($CFG->libdir.'/tablelib.php'); require_once($CFG->libdir.'/tablelib.php');
function stats_sumx($sum, $data){
$sum[0] += $data[0];
$sum[1] += $data[1];
return $sum;
}
function stats_sumx2($sum, $data){
$sum[0] += $data[0]*$data[0];
$sum[1] += $data[1]*$data[1];
return $sum;
}
function stats_sumxy($sum, $data){
$sum[0] += $data[0]*$data[1];
return $sum;
}
/// Item analysis displays a table of quiz questions and their performance /// Item analysis displays a table of quiz questions and their performance
class quiz_report extends quiz_default_report { class quiz_report extends quiz_default_report {
@ -80,7 +60,7 @@ class quiz_report extends quiz_default_report {
$scorelimit = $quiz->grade * $lowmarklimit/ 100; $scorelimit = $quiz->grade * $lowmarklimit/ 100;
// ULPGC ecastro DEBUG this is here to allow for differnt SQL to select attempts // ULPGC ecastro DEBUG this is here to allow for different SQL to select attempts
switch ($attemptselection) { switch ($attemptselection) {
case QUIZ_ALLATTEMPTS : case QUIZ_ALLATTEMPTS :
$limit = ''; $limit = '';
@ -103,33 +83,40 @@ class quiz_report extends quiz_default_report {
$select = 'SELECT qa.* '.$limit; $select = 'SELECT qa.* '.$limit;
$sql = 'FROM '.$CFG->prefix.'user u '. $sql = 'FROM '.$CFG->prefix.'user u '.
'LEFT JOIN '.$CFG->prefix.'quiz_attempts qa ON u.id = qa.userid '. 'LEFT JOIN '.$CFG->prefix.'quiz_attempts qa ON u.id = qa.userid '.
'LEFT JOIN '.$CFG->prefix.'quiz_states qr ON qr.attempt = qa.id '. // es posible
'WHERE u.id IN ('.implode(',', array_keys($users)).') AND ( qa.quiz = '.$quiz->id.') '. // ULPGC ecastro 'WHERE u.id IN ('.implode(',', array_keys($users)).') AND ( qa.quiz = '.$quiz->id.') '. // ULPGC ecastro
' AND ( qa.sumgrades >= '.$scorelimit.' ) '; ' AND ( qa.sumgrades >= '.$scorelimit.' ) ';
// ^^^^^^ es posible seleccionar aquí TODOS los quizzes, como quiere Jussi, // ^^^^^^ es posible seleccionar aquí TODOS los quizzes, como quiere Jussi,
// pero habría que llevar la cuenta ed cada quiz para restaura las preguntas (quizquestions, states) // pero habría que llevar la cuenta ed cada quiz para restaura las preguntas (quizquestions, states)
/// Fetch the attempts /// Fetch the attempts
$attempts = get_records_sql($select.$sql.$group); $attempts = get_records_sql($select.$sql.$group);
if(empty($attempts)) { if(empty($attempts)) {
$this->print_header_and_tabs($cm, $course, $quiz, $reportmode="analysis");
print_heading($strnoattempts); print_heading($strnoattempts);
$this->print_options_form($quiz, $cm, $attemptselection, $lowmarklimit, $pagesize); $this->print_options_form($quiz, $cm, $attemptselection, $lowmarklimit, $pagesize);
return true; return true;
} }
/// Here we rewiew all attempts and record data to construct the table /// Here we rewiew all attempts and record data to construct the table
unset($questions); $questions = array();
unset($statstable); $statstable = array();
$questionarray = array();
foreach ($attempts as $attempt) {
$questionarray[] = quiz_questions_in_quiz($attempt->layout);
}
$questionlist = quiz_questions_in_quiz(implode(",", $questionarray));
$questionarray = array_unique(explode(",",$questionlist));
$questionlist = implode(",", $questionarray);
unset($questionarray);
$accepted_qtypes = array(SHORTANSWER, TRUEFALSE, MULTICHOICE, MATCH, NUMERICAL, CALCULATED);
foreach ($attempts as $attempt) { foreach ($attempts as $attempt) {
//print_object($attempt); // ULPGC ecastro debug eliminar
// print "<br/>Layout= ".$attempt->layout." <br/>";
$questionlist = quiz_questions_in_quiz($attempt->layout);
$sql = "SELECT q.*, i.grade AS maxgrade, i.id AS instance". $sql = "SELECT q.*, i.grade AS maxgrade, i.id AS instance".
" FROM {$CFG->prefix}quiz_questions q,". " FROM {$CFG->prefix}quiz_questions q,".
" {$CFG->prefix}quiz_question_instances i". " {$CFG->prefix}quiz_question_instances i".
" WHERE i.quiz = '$quiz->id' AND q.id = i.question". " WHERE i.quiz = '$quiz->id' AND q.id = i.question".
" AND q.id IN ($questionlist)"; " AND q.id IN ($questionlist)";
if (!$quizquestions = get_records_sql($sql)) { if (!$quizquestions = get_records_sql($sql)) {
error('No questions found'); error('No questions found');
} }
@ -145,13 +132,12 @@ class quiz_report extends quiz_default_report {
error('Could not restore question sessions'); error('Could not restore question sessions');
} }
$numbers = explode(',', $questionlist); $numbers = explode(',', $questionlist);
unset($statsrow);
$statsrow = array(); $statsrow = array();
foreach ($numbers as $i) { foreach ($numbers as $i) {
$accepted = array(SHORTANSWER, TRUEFALSE, MULTICHOICE, RANDOM, MATCH, NUMERICAL, CALCULATED); $qtype = ($quizquestions[$i]->qtype==4) ? $states[$i]->options->question->qtype : $quizquestions[$i]->qtype;
if (!in_array ($quizquestions[$i]->qtype, $accepted)){ if (!in_array ($qtype, $accepted_qtypes)){
continue; continue;
} }
$q = quiz_get_question_responses($quizquestions[$i], $states[$i]); $q = quiz_get_question_responses($quizquestions[$i], $states[$i]);
$qid = $q->id; $qid = $q->id;
if (!isset($questions[$qid])) { if (!isset($questions[$qid])) {
@ -167,16 +153,18 @@ class quiz_report extends quiz_default_report {
} }
$responses = quiz_get_question_actual_response($quizquestions[$i], $states[$i]); $responses = quiz_get_question_actual_response($quizquestions[$i], $states[$i]);
foreach ($responses as $resp){ foreach ($responses as $resp){
if ($key = array_search($resp, $questions[$qid]['responses'])) { if ($resp) {
$questions[$qid]['rcounts'][$key]++; if ($key = array_search($resp, $questions[$qid]['responses'])) {
} else { $questions[$qid]['rcounts'][$key]++;
$questions[$qid]['responses'][] = $resp;
$questions[$qid]['rcounts'][] = 1;
$test->responses[''] = $resp;
if ($QUIZ_QTYPES[$quizquestions[$i]->qtype]->compare_responses($quizquestions[$i], $states[$i], $test)) {
$questions[$qid]['credits'][] = 1;
} else { } else {
$questions[$qid]['credits'][] = 0; $test->responses = $QUIZ_QTYPES[$quizquestions[$i]->qtype]->get_correct_responses($quizquestions[$i], $states[$i]);
if ($key = $QUIZ_QTYPES[$quizquestions[$i]->qtype]->check_response($quizquestions[$i], $states[$i], $test)) {
$questions[$qid]['rcounts'][$key]++;
} else {
$questions[$qid]['responses'][] = $resp;
$questions[$qid]['rcounts'][] = 1;
$questions[$qid]['credits'][] = 0;
}
} }
} }
} }
@ -204,42 +192,21 @@ class quiz_report extends quiz_default_report {
/// Now check if asked download of data /// Now check if asked download of data
if ($download = optional_param('download', NULL)) { if ($download = optional_param('download', NULL)) {
//$dir = make_upload_directory($course->id."/quiz_reports");
$filename = clean_filename("$course->shortname ".format_string($quiz->name,true)); $filename = clean_filename("$course->shortname ".format_string($quiz->name,true));
switch ($download) { switch ($download) {
case "Excel" : case "Excel" :
$downloadfilename = $filename.".xls"; $this->Export_Excel($questions, $filename);
$this->Export_Excel($questions, $downloadfilename);
break; break;
case "OOo": case "OOo":
$downloadfilename = $filename.".sxw"; $this->Export_OOo($questions, $filename);
$this->Export_OOo($questions, $downloadfilename);
break; break;
case "CSV": case "CSV":
$downloadfilename = $filename.".txt"; $this->Export_CSV($questions, $filename);
$this->Export_CSV($questions, $downloadfilename);
break; break;
} }
} }
/// Define some strings
$strquizzes = get_string("modulenameplural", "quiz");
$strquiz = get_string("modulename", "quiz");
/// Print the page header
print_header_simple(format_string($quiz->name), "",
"<a href=\"index.php?id=$course->id\">$strquizzes</a>
-> ".format_string($quiz->name),
"", "", true, update_module_button($cm->id, $course->id, $strquiz), navmenu($course, $cm));
/// Print the tabs
$currenttab = 'reports';
$mode = 'anaylis';
include('tabs.php');
$this->print_header_and_tabs($cm, $course, $quiz, $reportmode="analysis");
/// Construct the table for this particular report /// Construct the table for this particular report
$tablecolumns = array('id', 'qname', 'answers', 'credits', 'rcounts', 'rpercent', 'facility', 'sd','discrimination_index', 'discrimination_coeff'); $tablecolumns = array('id', 'qname', 'answers', 'credits', 'rcounts', 'rpercent', 'facility', 'sd','discrimination_index', 'discrimination_coeff');
@ -285,8 +252,8 @@ class quiz_report extends quiz_default_report {
$tablesort = $table->get_sql_sort(); $tablesort = $table->get_sql_sort();
$sorts = explode(",",trim($tablesort)); $sorts = explode(",",trim($tablesort));
if ($tablesort and is_array($sorts)) { if ($tablesort and is_array($sorts)) {
unset($sortindex); $sortindex = array();
unset($sortorder); $sortorder = array ();
foreach ($sorts as $sort) { foreach ($sorts as $sort) {
$data = explode(" ",trim($sort)); $data = explode(" ",trim($sort));
$sortindex[] = trim($data[0]); $sortindex[] = trim($data[0]);
@ -363,8 +330,6 @@ class quiz_report extends quiz_default_report {
$table->data[$i][$col] = ""; $table->data[$i][$col] = "";
} }
} }
} }
echo '<div id="titlecontainer" class="quiz-report-title">'; echo '<div id="titlecontainer" class="quiz-report-title">';
@ -376,13 +341,6 @@ class quiz_report extends quiz_default_report {
$table->print_html(); $table->print_html();
$this->print_options_form($quiz, $cm, $attemptselection, $lowmarklimit, $pagesize); $this->print_options_form($quiz, $cm, $attemptselection, $lowmarklimit, $pagesize);
/*
if ($download) {
echo "<script language='Javascript'> window.open('".$CFG->wwwroot."/files/index.php?id=".$course->id."&wdir=/".
get_string('quizreportdir', 'quiz_analysis')."', '".get_string('reportanalysis', 'quiz_analysis')."'); \n</script>";
}
*/
return true; return true;
} }
@ -427,9 +385,12 @@ class quiz_report extends quiz_default_report {
print_single_button("report.php", $options, get_string("downloadexcel")); print_single_button("report.php", $options, get_string("downloadexcel"));
echo "</td>\n"; echo "</td>\n";
echo '<td>'; echo '<td>';
$options["download"] = "OOo";
print_single_button("report.php", $options, get_string("downloadooo", "quiz_analysis")); if (file_exists("$CFG->libdir/phpdocwriter/lib/include.php")) {
echo "</td>\n"; $options["download"] = "OOo";
print_single_button("report.php", $options, get_string("downloadooo", "quiz_analysis"));
echo "</td>\n";
}
echo '<td>'; echo '<td>';
$options["download"] = "CSV"; $options["download"] = "CSV";
print_single_button('report.php', $options, get_string("downloadtext")); print_single_button('report.php', $options, get_string("downloadtext"));
@ -441,7 +402,7 @@ class quiz_report extends quiz_default_report {
} }
function report_question_stats(&$q, &$attemptscores, &$questionscores, $top, $bottom) { function report_question_stats(&$q, &$attemptscores, &$questionscores, $top, $bottom) {
unset($qstats); $qstats = array();
$qid = $q['id']; $qid = $q['id'];
$top_scores = $top_count = 0; $top_scores = $top_count = 0;
$bottom_scores = $bottom_count = 0; $bottom_scores = $bottom_count = 0;
@ -459,6 +420,9 @@ class quiz_report extends quiz_default_report {
} }
} }
//$sumx = array_reduce($qscores, "sumx");
$n = count($qstats); $n = count($qstats);
$sumx = array_reduce($qstats, "stats_sumx"); $sumx = array_reduce($qstats, "stats_sumx");
$sumg = $sumx[0]; $sumg = $sumx[0];
@ -492,7 +456,8 @@ class quiz_report extends quiz_default_report {
global $CFG; global $CFG;
require_once("$CFG->libdir/excel/Worksheet.php"); require_once("$CFG->libdir/excel/Worksheet.php");
require_once("$CFG->libdir/excel/Workbook.php"); require_once("$CFG->libdir/excel/Workbook.php");
$filename .= ".xls";
header("Content-Type: application/vnd.ms-excel"); header("Content-Type: application/vnd.ms-excel");
header("Content-Disposition: attachment; filename=\"$filename\""); header("Content-Disposition: attachment; filename=\"$filename\"");
header("Expires: 0"); header("Expires: 0");
@ -571,6 +536,10 @@ class quiz_report extends quiz_default_report {
function Export_OOo(&$questions, $filename) { function Export_OOo(&$questions, $filename) {
global $CFG; global $CFG;
require_once("$CFG->libdir/phpdocwriter/lib/include.php");
import('phpdocwriter.pdw_document');
$filename .= ".sxw";
header("Content-Type: application/download\n"); header("Content-Type: application/download\n");
header("Content-Disposition: attachment; filename=\"$filename\""); header("Content-Disposition: attachment; filename=\"$filename\"");
@ -579,8 +548,6 @@ class quiz_report extends quiz_default_report {
header("Pragma: public"); header("Pragma: public");
header("Content-Transfer-Encoding: binary"); header("Content-Transfer-Encoding: binary");
require_once("$CFG->libdir/phpdocwriter/lib/include.php");
import('phpdocwriter.pdw_document');
$filename = substr($filename, 0, -4); $filename = substr($filename, 0, -4);
$sxw = new pdw_document; $sxw = new pdw_document;
@ -628,6 +595,8 @@ class quiz_report extends quiz_default_report {
get_string('dicsindextitle','quiz_analysis'), get_string('disccoefftitle','quiz_analysis')); get_string('dicsindextitle','quiz_analysis'), get_string('disccoefftitle','quiz_analysis'));
$text = implode("\t", $headers)." \n"; $text = implode("\t", $headers)." \n";
$filename .= ".txt";
header("Content-Type: application/download\n"); header("Content-Type: application/download\n");
header("Content-Disposition: attachment; filename=\"$filename\""); header("Content-Disposition: attachment; filename=\"$filename\"");
@ -690,13 +659,25 @@ class quiz_report extends quiz_default_report {
} }
return $result; return $result;
} }
}
function stats_sumx($sum, $data){
$sum[0] += $data[0];
$sum[1] += $data[1];
return $sum;
}
function stats_sumx2($sum, $data){
$sum[0] += $data[0]*$data[0];
$sum[1] += $data[1]*$data[1];
return $sum;
}
function stats_sumxy($sum, $data){
$sum[0] += $data[0]*$data[1];
return $sum;
} }
?> ?>

View file

@ -21,6 +21,20 @@ class quiz_default_report {
return true; return true;
} }
function print_header_and_tabs($cm, $course, $quiz, $reportmode="simplestat"){
/// Define some strings
$strquizzes = get_string("modulenameplural", "quiz");
$strquiz = get_string("modulename", "quiz");
/// Print the page header
print_header_simple(format_string($quiz->name), "",
"<a href=\"index.php?id=$course->id\">$strquizzes</a>
-> ".format_string($quiz->name),
"", "", true, update_module_button($cm->id, $course->id, $strquiz), navmenu($course, $cm));
/// Print the tabs
$currenttab = 'reports';
$mode = $reportmode;
include('tabs.php');
}
} }
?> ?>