MDL-41757 quiz statistics : limit subq and variant stat rows
authorJames Pratt <me@jamiep.org>
Sun, 1 Dec 2013 10:24:42 +0000 (17:24 +0700)
committerJames Pratt <me@jamiep.org>
Mon, 27 Jan 2014 11:04:08 +0000 (18:04 +0700)
and print min, median and max.

mod/quiz/report/statistics/lang/en/quiz_statistics.php
mod/quiz/report/statistics/report.php
mod/quiz/report/statistics/statistics_table.php
question/classes/statistics/questions/calculated.php

index 98f2b93..d068602 100644 (file)
@@ -64,7 +64,10 @@ $string['kurtosis'] = 'Score distribution kurtosis (for {$a})';
 $string['lastattempts'] = 'last attempt';
 $string['lastattemptsavg'] = 'Average grade of last attempts';
 $string['lastcalculated'] = 'Last calculated {$a->lastcalculated} ago there have been {$a->count} attempts since then.';
+$string['maximumfacility'] = 'Maximum facility';
 $string['median'] = 'Median grade (for {$a})';
+$string['medianfacility'] = 'Median facility';
+$string['minimumfacility'] = 'Minimum facility';
 $string['modelresponse'] = 'Model response';
 $string['nameforvariant'] = 'Variant {$a->variant} of {$a->name}';
 $string['negcovar'] = 'Negative covariance of grade with total attempt grade';
index fe09d91..148ea39 100644 (file)
@@ -38,6 +38,8 @@ require_once($CFG->dirroot . '/mod/quiz/report/statistics/statisticslib.php');
  */
 class quiz_statistics_report extends quiz_default_report {
 
+    const SUBQ_AND_VARIANT_ROW_LIMIT = 10;
+
     /**
      * @var context_module
      */
@@ -413,39 +415,94 @@ class quiz_statistics_report extends quiz_default_report {
             // Output the data for these question statistics.
             $this->table->add_data_keyed($this->table->format_row($questionstat));
             if (count($questionstat->variantstats) > 1) {
-                ksort($questionstat->variantstats);
-                foreach ($questionstat->variantstats as $variantstat) {
-                    $this->table->add_data_keyed($this->table->format_row($variantstat));
+                if (count($questionstat->variantstats) > static::SUBQ_AND_VARIANT_ROW_LIMIT) {
+                    $statstoadd = $this->find_min_median_and_max_facility_stats_objects($questionstat->variantstats);
+                } else {
+                    ksort($questionstat->variantstats);
+                    $statstoadd = $questionstat->variantstats;
                 }
+                $this->add_array_of_rows_to_table($statstoadd);
             }
 
             if (empty($questionstat->subquestions)) {
                 continue;
             }
 
-            // And its subquestions, if it has any.
+            // And its sub-questions, if it has any.
             $subitemstodisplay = explode(',', $questionstat->subquestions);
+
+            // We need to get all variants out of sub-questions to count them and possibly find min, median and max.
             $displayorder = 1;
+            $subqvariants = array();
             foreach ($subitemstodisplay as $subitemid) {
-                $subquestionstats[$subitemid]->maxmark = $questionstat->maxmark;
-                $subquestionstats[$subitemid]->subqdisplayorder = $displayorder;
-                $subquestionstats[$subitemid]->question->number = $questionstat->question->number;
-                $this->table->add_data_keyed($this->table->format_row($subquestionstats[$subitemid]));
                 if (count($subquestionstats[$subitemid]->variantstats) > 1) {
                     ksort($subquestionstats[$subitemid]->variantstats);
                     foreach ($subquestionstats[$subitemid]->variantstats as $variantstat) {
                         $variantstat->subqdisplayorder = $displayorder;
                         $variantstat->question->number = $questionstat->question->number;
-                        $this->table->add_data_keyed($this->table->format_row($variantstat));
+                        $subqvariants[] = $variantstat;
                     }
                 }
                 $displayorder++;
             }
+            if (count($subqvariants) > static::SUBQ_AND_VARIANT_ROW_LIMIT) {
+                // Too many variants from randomly selected questions.
+                $toadd = $this->find_min_median_and_max_facility_stats_objects($subqvariants);
+                $this->add_array_of_rows_to_table($toadd);
+            } else if (count($subitemstodisplay) > static::SUBQ_AND_VARIANT_ROW_LIMIT) {
+                // Too many randomly selected questions.
+                $toadd = $this->find_min_median_and_max_facility_stats_objects($subitemstodisplay);
+                $this->add_array_of_rows_to_table($toadd);
+            } else {
+                foreach ($subitemstodisplay as $subitemid) {
+                    $subquestionstats[$subitemid]->maxmark = $questionstat->maxmark;
+                    $subquestionstats[$subitemid]->subqdisplayorder = $displayorder;
+                    $subquestionstats[$subitemid]->question->number = $questionstat->question->number;
+                    $this->table->add_data_keyed($this->table->format_row($subquestionstats[$subitemid]));
+                    if (count($subquestionstats[$subitemid]->variantstats) > 1) {
+                        ksort($subquestionstats[$subitemid]->variantstats);
+                        foreach ($subquestionstats[$subitemid]->variantstats as $variantstat) {
+                            $this->table->add_data_keyed($this->table->format_row($variantstat));
+                        }
+                    }
+                }
+            }
+
         }
 
         $this->table->finish_output(!$this->table->is_downloading());
     }
 
+    protected function find_min_median_and_max_facility_stats_objects($questionstats) {
+        $facilities = array();
+        foreach ($questionstats as $key => $questionstat) {
+            $facilities[$key] = (float)$questionstat->facility;
+        }
+        asort($facilities);
+        $facilitykeys = array_keys($facilities);
+        $keyformin = $facilitykeys[0];
+        $keyformedian = $facilitykeys[(int)(round(count($facilitykeys) / 2)-1)];
+        $keyformax = $facilitykeys[count($facilitykeys) - 1];
+        $toreturn = array();
+        foreach (array($keyformin => 'minimumfacility',
+                       $keyformedian => 'medianfacility',
+                       $keyformax => 'maximumfacility') as $key => $stringid) {
+            $questionstats[$key]->minmedianmaxnotice = get_string($stringid, 'quiz_statistics');
+            $toreturn[] = $questionstats[$key];
+        }
+        return $toreturn;
+    }
+
+
+    /**
+     * @param \core_question\statistics\questions\calculator $statstoadd
+     */
+    protected function add_array_of_rows_to_table($statstoadd) {
+        foreach ($statstoadd as $stattoadd) {
+            $this->table->add_data_keyed($this->table->format_row($stattoadd));
+        }
+    }
+
     /**
      * Output the table of overall quiz statistics.
      * @param array $quizinfo as returned by {@link get_formatted_quiz_info_data()}.
index c295e51..1449616 100644 (file)
@@ -138,7 +138,7 @@ class quiz_statistics_table extends flexible_table {
     protected function col_number($questionstat) {
         $number = $questionstat->question->number;
 
-        if ($questionstat->subquestion) {
+        if (isset($questionstat->subqdisplayorder)) {
             $number = $number . '.'.$questionstat->subqdisplayorder;
         }
 
@@ -213,6 +213,10 @@ class quiz_statistics_table extends flexible_table {
             $name = html_writer::tag('div', $name, array('class' => 'dubious'));
         }
 
+        if (!empty($questionstat->minmedianmaxnotice)) {
+            $name = $questionstat->minmedianmaxnotice . '<br />' . $name;
+        }
+
         return $name;
     }
 
index 3d8b652..198212a 100644 (file)
@@ -55,6 +55,12 @@ class calculated {
      */
     public $subquestion = false;
 
+    /**
+     * @var string if this stat has been picked as a min, median or maximum facility value then this string says which stat this
+     *                  is.
+     */
+    public $minmedianmaxnotice = '';
+
     /**
      * @var int total attempts at this question.
      */