From ea751786e026708849dbb54d12fdde98ddbfd967 Mon Sep 17 00:00:00 2001 From: jamiesensei Date: Wed, 16 Jul 2008 11:55:38 +0000 Subject: [PATCH] MDL-15268 "Content for Quiz Statistics report table" know looping through all question grades fetched from the db to calculate position statistics. --- lang/en_utf8/quiz_statistics.php | 6 +- mod/quiz/report/statistics/report.php | 115 +++++++++++++++++- .../report/statistics/statistics_table.php | 26 +++- 3 files changed, 139 insertions(+), 8 deletions(-) diff --git a/lang/en_utf8/quiz_statistics.php b/lang/en_utf8/quiz_statistics.php index 1a5d13764c..c51bef67a8 100644 --- a/lang/en_utf8/quiz_statistics.php +++ b/lang/en_utf8/quiz_statistics.php @@ -24,6 +24,7 @@ $string['attemptsfirst'] = 'first attempt'; $string['errormedian'] = 'Error fetching median'; $string['errorpowers'] = 'Error fetching data to calculate variance for quiz grades'; $string['errorpowerquestions'] = 'Error fetching data to calculate variance for question grades'; +$string['errorstatisticsquestions'] = 'Error fetching data to calculate statistics for question grades'; $string['median'] = 'Median grade'; $string['standarddeviation'] = 'Standard deviation'; $string['skewness'] = 'Score distribution skewness'; @@ -34,8 +35,11 @@ $string['standarderror'] = 'Standard error'; $string['questionnumber'] = 'Q#'; $string['quizstructureanalysis'] = 'Quiz structure analysis'; $string['questiontype'] = 'Q type'; -$string['intended_weight'] = 'Intended question weight'; +$string['intended_weight'] = 'Intended weight'; $string['random_guess_score'] = 'Random guess score'; $string['facility'] = 'Facility index'; $string['nostudentsingroup'] = 'There are no students in this group yet'; +$string['discrimination_index'] = 'Discrimination Index'; +$string['discriminative_efficiency'] = 'Discriminative Efficiency'; +$string['effective_weight'] = 'Effective weight'; ?> \ No newline at end of file diff --git a/mod/quiz/report/statistics/report.php b/mod/quiz/report/statistics/report.php index b782dc070b..9e4c2659c4 100644 --- a/mod/quiz/report/statistics/report.php +++ b/mod/quiz/report/statistics/report.php @@ -144,6 +144,7 @@ class quiz_statistics_report extends quiz_default_report { } $usingattempts->heading = get_string('statsfor', 'quiz_statistics', $usingattempts->attempts); $s = $usingattempts->countrecs; + $sumgradesavg = $usingattempts->total / $usingattempts->countrecs; } } else { $s = 0; @@ -243,11 +244,14 @@ class quiz_statistics_report extends quiz_default_report { } } if ($s){ - //CIC, ER and SE. +/* //CIC, ER and SE. //http://docs.moodle.org/en/Development:Quiz_item_analysis_calculations_in_practise#CIC.2C_ER_and_SE list($qsql, $sqlparams) = $DB->get_in_or_equal(array_keys($questions), SQL_PARAMS_NAMED); $sqlparams += $qaparams;//put quiz id in at beginning of array - $qgradeavgsql = "SELECT qs.question, AVG(qs.grade) FROM " . + $qgradeavgsql = "SELECT qs.question, " . + "AVG(qs.grade) AS gradeaverage " . + "AVG(qa.sumgrades - qs.grade) AS sumgradeaverage " . + "FROM " . "{question_sessions} qns, " . "{question_states} qs, " . $fromqa.' '. @@ -256,7 +260,7 @@ class quiz_statistics_report extends quiz_default_report { 'AND qs.question '.$qsql.' ' . $usingattempts->sql. 'AND qns.newgraded = qs.id GROUP BY qs.question'; - $qgradeavgs = $DB->get_records_sql_menu($qgradeavgsql, $sqlparams); + $qgradeavgs = $DB->get_records_sql($qgradeavgsql, $sqlparams); $sum = 0; $sql = 'SELECT COUNT(1) as s,' . @@ -283,13 +287,112 @@ class quiz_statistics_report extends quiz_default_report { } $sum += $fromdb->power2; } + //Discrimination index + $sql = 'SELECT qs.id, ' . + 'qs.question, ' . + 'qa.sumgrades - qs.grade AS sum, ' . + 'qs.grade ' . + 'FROM ' . + '{question_sessions} qns, ' . + '{question_states} qs, '. + $fromqa.' '. + 'WHERE ' .$whereqa. + 'AND qns.attemptid = qa.uniqueid '. + $usingattempts->sql. + 'AND qns.newgraded = qs.id'; + $fromdbrs = $DB->get_recordset_sql($sql, $qaparams); + if ($fromdbrs === false){ + print_error('errorpowerquestions', 'quiz_statistics'); + } + foreach ($fromdbrs as $record){ + + }*/ + $sql = 'SELECT qs.id, ' . + 'qs.question, ' . + 'qa.sumgrades, ' . + 'qs.grade ' . + 'FROM ' . + '{question_sessions} qns, ' . + '{question_states} qs, '. + $fromqa.' '. + 'WHERE ' .$whereqa. + 'AND qns.attemptid = qa.uniqueid '. + $usingattempts->sql. + 'AND qns.newgraded = qs.id'; + $fromdbrs = $DB->get_recordset_sql($sql, $qaparams); + if ($fromdbrs === false){ + print_error('errorstatisticsquestions', 'quiz_statistics'); + } + foreach (array_keys($questions) as $qid){ + $questions[$qid]->s = 0; + $questions[$qid]->totalgrades = 0; + $questions[$qid]->totalothergrades = 0; + $questions[$qid]->gradevariancesum = 0; + $questions[$qid]->othergradevariancesum = 0; + $questions[$qid]->covariancesum = 0; + $questions[$qid]->covariancemaxsum = 0; + $questions[$qid]->covariancewithoverallgradesum = 0; + $questions[$qid]->gradearray = array(); + $questions[$qid]->othergradesarray = array(); + } + + foreach ($fromdbrs as $record){ + $questions[$record->question]->s++; + $questions[$record->question]->totalgrades += $record->grade; + $questions[$record->question]->totalothergrades += $record->sumgrades - $record->grade; + //need to sort these to calculate max covariance : + $questions[$record->question]->gradearray[] = $record->grade; + $questions[$record->question]->othergradesarray[] = $record->sumgrades - $record->grade; + } + foreach (array_keys($questions) as $qid){ + $questions[$qid]->gradeaverage = $questions[$qid]->totalgrades / $s; + $questions[$qid]->facility = $questions[$qid]->gradeaverage / $questions[$qid]->grade; + $questions[$qid]->othergradeaverage = $questions[$qid]->totalothergrades / $s; + sort($questions[$qid]->gradearray, SORT_NUMERIC); + sort($questions[$qid]->othergradesarray, SORT_NUMERIC); + } + //go through the records one more time + foreach ($fromdbrs as $record){ + $gradedifference = ($record->grade - $questions[$record->question]->gradeaverage); + $othergradedifference = (($record->sumgrades - $record->grade) - $questions[$record->question]->othergradeaverage); + $overallgradedifference = $record->sumgrades - $sumgradesavg; + $sortedgradedifference = (array_shift($questions[$qid]->gradearray) - $questions[$record->question]->gradeaverage); + $sortedothergradedifference = (array_shift($questions[$qid]->othergradesarray) - $questions[$record->question]->othergradeaverage); + $questions[$record->question]->gradevariancesum += pow($gradedifference,2); + $questions[$record->question]->othergradevariancesum += pow($othergradedifference,2); + $questions[$record->question]->covariancesum += $gradedifference * $othergradedifference; + $questions[$record->question]->covariancemaxsum += $sortedgradedifference * $sortedothergradedifference; + $questions[$record->question]->covariancewithoverallgradesum += $gradedifference * $overallgradedifference; + } + $sumofcovariancewithoverallgrade = 0; + $sumofgradevariance =0; + foreach (array_keys($questions) as $qid){ + $questions[$qid]->gradevariance = $questions[$qid]->gradevariancesum / ($s -1); + $questions[$qid]->othergradevariance = $questions[$qid]->othergradevariancesum / ($s -1); + $questions[$qid]->covariance = $questions[$qid]->covariancesum / ($s -1); + $questions[$qid]->covariancemax = $questions[$qid]->covariancemaxsum / ($s -1); + $sumofgradevariance += $questions[$qid]->gradevariance; + $questions[$qid]->covariancewithoverallgrade = $questions[$qid]->covariancewithoverallgradesum / ($s-1); + $sumofcovariancewithoverallgrade += sqrt($questions[$qid]->covariancewithoverallgrade); + $questions[$qid]->sd = sqrt($questions[$qid]->gradevariancesum / ($s -1)); + //avoid divide by zero + if (sqrt($questions[$qid]->gradevariance * $questions[$qid]->othergradevariance)){ + $questions[$qid]->discriminationindex = 100*$questions[$qid]->covariance + / sqrt($questions[$qid]->gradevariance * $questions[$qid]->othergradevariance); + } else { + $questions[$qid]->discriminationindex = ''; + } + $questions[$qid]->discriminativeefficiency = 100*$questions[$qid]->covariance / $questions[$qid]->covariancemax; + } + foreach (array_keys($questions) as $qid){ + $questions[$qid]->effectiveweight = 100 * sqrt($questions[$qid]->covariancewithoverallgrade)/$sumofcovariancewithoverallgrade; + } } if (!$table->is_downloading()){ if ($s>1){ - $sumofvarianceforallpositions = $sum / ($s -1); - $p = count($qgradeavgs);//no of positions + $p = count($questions);//no of positions if ($p > 1){ - $cic = (100 * $p / ($p -1)) * (1 - ($sumofvarianceforallpositions/$k2)); + $cic = (100 * $p / ($p -1)) * (1 - ($sumofgradevariance)/$k2); $quizattsstatistics->data[] = array(get_string('cic', 'quiz_statistics'), number_format($cic, $quiz->decimalpoints).' %'); $errorratio = 100 * sqrt(1-($cic/100)); $quizattsstatistics->data[] = array(get_string('errorratio', 'quiz_statistics'), number_format($errorratio, $quiz->decimalpoints).' %'); diff --git a/mod/quiz/report/statistics/statistics_table.php b/mod/quiz/report/statistics/statistics_table.php index 6de8aef07f..ebf425363f 100644 --- a/mod/quiz/report/statistics/statistics_table.php +++ b/mod/quiz/report/statistics/statistics_table.php @@ -51,6 +51,15 @@ class quiz_report_statistics_table extends flexible_table { $columns[]= 'intended_weight'; $headers[]= get_string('intended_weight', 'quiz_statistics'); + $columns[]= 'effective_weight'; + $headers[]= get_string('effective_weight', 'quiz_statistics'); + + $columns[]= 'discrimination_index'; + $headers[]= get_string('discrimination_index', 'quiz_statistics'); + + $columns[]= 'discriminative_efficiency'; + $headers[]= get_string('discriminative_efficiency', 'quiz_statistics'); + $this->define_columns($columns); $this->define_headers($headers); $this->sortable(false); @@ -58,8 +67,11 @@ class quiz_report_statistics_table extends flexible_table { $this->column_class('s', 'numcol'); $this->column_class('random_guess_score', 'numcol'); $this->column_class('intended_weight', 'numcol'); + $this->column_class('effective_weight', 'numcol'); $this->column_class('sd', 'numcol'); $this->column_class('facility', 'numcol'); + $this->column_class('discrimination_index', 'numcol'); + $this->column_class('discriminative_efficiency', 'numcol'); // Set up the table $this->define_baseurl($reporturl->out()); @@ -107,7 +119,19 @@ class quiz_report_statistics_table extends flexible_table { function col_intended_weight($question){ return quiz_report_scale_sumgrades_as_percentage($question->grade, $this->quiz); } - + function col_effective_weight($question){ + return number_format($question->effectiveweight, 2).' %'; + } + function col_discrimination_index($question){ + if (is_numeric($question->discriminationindex)){ + return number_format($question->discriminationindex, 2).' %'; + } else { + return $question->discriminationindex; + } + } + function col_discriminative_efficiency($question){ + return number_format($question->discriminativeefficiency, 2).' %'; + } function col_random_guess_score($question){ $randomguessscore = question_get_random_guess_score($question); if (is_numeric($randomguessscore)){ -- 2.39.5