diff --git a/lang/en_utf8/quiz_statistics.php b/lang/en_utf8/quiz_statistics.php index 052101f500f..3a230bf4a8a 100644 --- a/lang/en_utf8/quiz_statistics.php +++ b/lang/en_utf8/quiz_statistics.php @@ -36,4 +36,5 @@ $string['questiontype'] = 'Q type'; $string['intended_weight'] = 'Intended question weight'; $string['random_guess_score'] = 'Random guess score'; $string['facility'] = 'Facility index'; +$string['nostudentsingroup'] = 'There are no students in this group yet'; ?> \ No newline at end of file diff --git a/mod/quiz/report/statistics/report.php b/mod/quiz/report/statistics/report.php index e3ba4537fe9..48dbc6377cc 100644 --- a/mod/quiz/report/statistics/report.php +++ b/mod/quiz/report/statistics/report.php @@ -45,13 +45,13 @@ class quiz_report extends quiz_default_report { /// find out current groups mode $currentgroup = groups_get_activity_group($cm, true); + $nostudentsingroup = false;//true if a group is selected and their is noeone in it. if (!empty($currentgroup)) { // all users who can attempt quizzes and who are in the currently selected group - if (!$groupstudents = get_users_by_capability($context, 'mod/quiz:attempt','','','','',$currentgroup,'',false)){ - $groupstudents = array(); + $groupstudents = get_users_by_capability($context, 'mod/quiz:attempt','','','','',$currentgroup,'',false); + if (!$groupstudents){ + $nostudentsingroup = true; } - $groupstudentslist = join(',', array_keys($groupstudents)); - $allowedlist = $groupstudentslist; } $questions = quiz_report_load_questions($quiz); @@ -71,6 +71,9 @@ class quiz_report extends quiz_default_report { if ($groupmode = groups_get_activity_groupmode($cm)) { // Groups are being used if (!$table->is_downloading()) { groups_print_activity_menu($cm, $reporturl->out()); + if ($currentgroup && !$groupstudents){ + notify(get_string('nostudentsingroup', 'quiz_statistics')); + } } } @@ -105,27 +108,48 @@ class quiz_report extends quiz_default_report { $mform->display(); } $fromqa = '{quiz_attempts} qa '; - $whereqa = 'quiz = ? AND preview=0 AND timefinish !=0 '; + $whereqa = 'quiz = :quizid AND preview=0 AND timefinish !=0 '; + $qaparams = array('quizid'=>$quiz->id); + if (!empty($currentgroup) && $groupstudents) { + list($grpsql, $grpparams) = $DB->get_in_or_equal(array_keys($groupstudents), SQL_PARAMS_NAMED, 'u0000'); + $whereqa .= ' AND qa.userid '.$grpsql.' '; + $qaparams += $grpparams; + } $sql = 'SELECT (attempt=1) AS isfirst, COUNT(1) AS countrecs, SUM(sumgrades) AS total ' . 'FROM '.$fromqa. 'WHERE ' .$whereqa. 'GROUP BY (attempt=1)'; - //Calculating_MEAN_of_grades_for_all_attempts_by_students - //http://docs.moodle.org/en/Development:Quiz_item_analysis_calculations_in_practise#Calculating_MEAN_of_grades_for_all_attempts_by_students - if (!$attempttotals = $DB->get_records_sql($sql, array($quiz->id))){ - print_heading(get_string('noattempts','quiz')); - return true; + if (!$nostudentsingroup){ + //Calculating_MEAN_of_grades_for_all_attempts_by_students + //http://docs.moodle.org/en/Development:Quiz_item_analysis_calculations_in_practise#Calculating_MEAN_of_grades_for_all_attempts_by_students + if (!$attempttotals = $DB->get_records_sql($sql, $qaparams)){ + print_heading(get_string('noattempts','quiz')); + $s = 0; + } else { + $firstattempt = $attempttotals[1]; + $allattempts = new object(); + $allattempts->countrecs = $firstattempt->countrecs + + (isset($attempttotals[0])?$attempttotals[0]->countrecs:0); + $allattempts->total = $firstattempt->total + + (isset($attempttotals[0])?$attempttotals[0]->total:0); + if ($useallattempts){ + $usingattempts = $allattempts; + $usingattempts->attempts = get_string('allattempts', 'quiz_statistics'); + $usingattempts->sql = ''; + } else { + $usingattempts = $firstattempt; + $usingattempts->attempts = get_string('firstattempts', 'quiz_statistics'); + $usingattempts->sql = 'AND qa.attempt=1 '; + } + $usingattempts->heading = get_string('statsfor', 'quiz_statistics', $usingattempts->attempts); + $s = $usingattempts->countrecs; + } } else { - $firstattempt = $attempttotals[1]; - $allattempts = new object(); - $allattempts->countrecs = $firstattempt->countrecs + - (isset($attempttotals[0])?$attempttotals[0]->countrecs:0); - $allattempts->total = $firstattempt->total + - (isset($attempttotals[0])?$attempttotals[0]->total:0); + $s = 0; } - - if (!$table->is_downloading()) { + + if ($s && !$table->is_downloading()) { print_heading(get_string('quizoverallstatistics', 'quiz_statistics')); $quizoverallstatistics = new object(); $quizoverallstatistics->align = array('center', 'center'); @@ -138,25 +162,21 @@ class quiz_report extends quiz_default_report { $quizoverallstatistics->data[] = array(get_string('allattemptsavg', 'quiz_statistics'), quiz_report_scale_sumgrades_as_percentage($allattempts->total / $allattempts->countrecs, $quiz)); print_table($quizoverallstatistics); } + $quizattsstatistics = new object(); + $quizattsstatistics->align = array('center', 'center'); + $quizattsstatistics->width = '60%'; + $quizattsstatistics->class = 'generaltable titlesleft'; + $quizattsstatistics->data = array(); //get the median - if (!$table->is_downloading()) { - if ($useallattempts){ - $usingattempts = $allattempts; - $usingattempts->attempts = get_string('allattempts', 'quiz_statistics'); - $usingattempts->sql = ''; - } else { - $usingattempts = $firstattempt; - $usingattempts->attempts = get_string('firstattempts', 'quiz_statistics'); - $usingattempts->sql = 'AND qa.attempt=1 '; - } - $usingattempts->heading = get_string('statsfor', 'quiz_statistics', $usingattempts->attempts); + if ($s && !$table->is_downloading()) { + print_heading($usingattempts->heading); - if (($usingattempts->countrecs/2)==floor($usingattempts->countrecs/2)){ + if (($s%2)==0){ //even number of attempts - $limitoffset = (floor($usingattempts->countrecs/2)) - 1; + $limitoffset = ($s/2) - 1; $limit = 2; } else { - $limitoffset = ($usingattempts->countrecs/2) - 1; + $limitoffset = (floor($s/2)) - 1; $limit = 1; } $sql = 'SELECT id, sumgrades ' . @@ -164,7 +184,7 @@ class quiz_report extends quiz_default_report { 'WHERE ' .$whereqa. $usingattempts->sql. 'ORDER BY sumgrades'; - if (!$mediangrades = $DB->get_records_sql_menu($sql, array($quiz->id), $limitoffset, $limit)){ + if (!$mediangrades = $DB->get_records_sql_menu($sql, $qaparams, $limitoffset, $limit)){ print_error('errormedian', 'quiz_statistics'); } if (count($mediangrades)==1){ @@ -174,26 +194,19 @@ class quiz_report extends quiz_default_report { $median += array_shift($mediangrades); $median = $median /2; } - - $s = $usingattempts->countrecs; if ($s>1){ - $quizattsstatistics = new object(); - $quizattsstatistics->align = array('center', 'center'); - $quizattsstatistics->width = '60%'; - $quizattsstatistics->class = 'generaltable titlesleft'; - $quizattsstatistics->data = array(); $quizattsstatistics->data[] = array(get_string('median', 'quiz_statistics'), quiz_report_scale_sumgrades_as_percentage($median, $quiz)); //fetch sum of squared, cubed and power 4d //differences between grades and mean grade - $mean = $usingattempts->total / $usingattempts->countrecs; + $mean = $usingattempts->total / $s; $sql = "SELECT " . - "SUM(POWER((qa.sumgrades - ?),2)) AS power2, " . - "SUM(POWER((qa.sumgrades - ?),3)) AS power3, ". - "SUM(POWER((qa.sumgrades - ?),4)) AS power4 ". + "SUM(POWER((qa.sumgrades - :mean1),2)) AS power2, " . + "SUM(POWER((qa.sumgrades - :mean2),3)) AS power3, ". + "SUM(POWER((qa.sumgrades - :mean3),4)) AS power4 ". 'FROM ' .$fromqa. 'WHERE ' .$whereqa. $usingattempts->sql; - $params = array($mean, $mean, $mean, $quiz->id); + $params = array('mean1' => $mean, 'mean2' => $mean, 'mean3' => $mean)+$qaparams; if (!$powers = $DB->get_record_sql($sql, $params)){ print_error('errorpowers', 'quiz_statistics'); } @@ -227,46 +240,53 @@ class quiz_report extends quiz_default_report { $quizattsstatistics->data[] = array(get_string('kurtosis', 'quiz_statistics'), $kurtosis); } - //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_QM); - array_unshift($sqlparams, $quiz->id);//put quiz id in at beginning of array - $qgradeavgsql = "SELECT qs.question, AVG(qs.grade) FROM " . - "{question_sessions} qns, " . - "{question_states} qs, " . - $fromqa.' '. - 'WHERE ' .$whereqa. - 'AND qns.attemptid = qa.uniqueid '. - 'AND qs.question '.$qsql.' ' . - $usingattempts->sql. - 'AND qns.newgraded = qs.id GROUP BY qs.question'; - $qgradeavgs = $DB->get_records_sql_menu($qgradeavgsql, $sqlparams); - - $sum = 0; - $sql = 'SELECT COUNT(1) as s,' . - 'SUM(POWER((qs.grade - ?),2)) AS power2 ' . - 'FROM ' . - '{question_sessions} qns, ' . - '{question_states} qs, '. - $fromqa.' '. - 'WHERE ' .$whereqa. - 'AND qns.attemptid = qa.uniqueid '. - 'AND qs.question = ? ' . - $usingattempts->sql. - 'AND qns.newgraded = qs.id'; - foreach ($qgradeavgs as $qid => $qgradeavg){ - $params = array($qgradeavg, $quiz->id, $qid); - $fromdb = $DB->get_record_sql($sql, $params); - if ($fromdb === false){ - print_error('errorpowerquestions', 'quiz_statistics'); - } - $questions[$qid]->facility = $qgradeavg / $questions[$qid]->grade; - $questions[$qid]->power = $fromdb->power2; - $questions[$qid]->s = $fromdb->s; - $questions[$qid]->sd = sqrt($questions[$qid]->power / ($questions[$qid]->s -1)); - $sum += $questions[$qid]->power; + } + } + if ($s){ + //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 " . + "{question_sessions} qns, " . + "{question_states} qs, " . + $fromqa.' '. + 'WHERE ' .$whereqa. + 'AND qns.attemptid = qa.uniqueid '. + 'AND qs.question '.$qsql.' ' . + $usingattempts->sql. + 'AND qns.newgraded = qs.id GROUP BY qs.question'; + $qgradeavgs = $DB->get_records_sql_menu($qgradeavgsql, $sqlparams); + + $sum = 0; + $sql = 'SELECT COUNT(1) as s,' . + 'SUM(POWER((qs.grade - :mean),2)) AS power2 ' . + 'FROM ' . + '{question_sessions} qns, ' . + '{question_states} qs, '. + $fromqa.' '. + 'WHERE ' .$whereqa. + 'AND qns.attemptid = qa.uniqueid '. + 'AND qs.question = :qid ' . + $usingattempts->sql. + 'AND qns.newgraded = qs.id'; + foreach (array_keys($questions) as $qid){ + $params = array('mean' => $qgradeavgs[$qid], 'qid' => $qid)+ $qaparams; + $fromdb = $DB->get_record_sql($sql, $params); + if ($fromdb === false){ + print_error('errorpowerquestions', 'quiz_statistics'); } - $sumofvarianceforallpositions = $sum / ($usingattempts->countrecs -1); + $questions[$qid]->s = $fromdb->s; + if ($s>1){ + $questions[$qid]->facility = $qgradeavgs[$qid] / $questions[$qid]->grade; + $questions[$qid]->sd = sqrt($fromdb->power2 / ($questions[$qid]->s -1)); + } + $sum += $fromdb->power2; + } + } + if (!$table->is_downloading()){ + if ($s>1){ + $sumofvarianceforallpositions = $sum / ($s -1); $p = count($qgradeavgs);//no of positions if ($p > 1){ $cic = (100 * $p / ($p -1)) * (1 - ($sumofvarianceforallpositions/$k2)); @@ -277,9 +297,10 @@ class quiz_report extends quiz_default_report { $quizattsstatistics->data[] = array(get_string('standarderror', 'quiz_statistics'), quiz_report_scale_sumgrades_as_percentage($standarderror, $quiz)); } + } + if ($quizattsstatistics->data){ print_table($quizattsstatistics); } - } if (!$table->is_downloading()){ print_heading(get_string('quizstructureanalysis', 'quiz_statistics')); diff --git a/mod/quiz/report/statistics/statistics_table.php b/mod/quiz/report/statistics/statistics_table.php index d567a2d1dcb..6de8aef07fd 100644 --- a/mod/quiz/report/statistics/statistics_table.php +++ b/mod/quiz/report/statistics/statistics_table.php @@ -121,7 +121,11 @@ class quiz_report_statistics_table extends flexible_table { return number_format($question->sd*100 / $question->grade, 2).' %'; } function col_s($question){ - return $question->s; + if (isset($question->s)){ + return $question->s; + } else { + return 0; + } } function col_facility($question){ return number_format($question->facility*100, 2).' %';