Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   *
  19   * Data structure to count responses for each of the sub parts of a question.
  20   *
  21   * @package    core_question
  22   * @copyright  2014 The Open University
  23   * @author     James Pratt me@jamiep.org
  24   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  25   */
  26  
  27  namespace core_question\statistics\responses;
  28  
  29  /**
  30   * Representing the analysis of each of the sub parts of each variant of the question.
  31   *
  32   * - There is a separate data structure for each question or sub question's analysis
  33   * {@link \core_question\statistics\responses\analysis_for_question}
  34   * or {@link \core_question\statistics\responses\analysis_for_question_all_tries}.
  35   * - There are separate analysis for each variant in this top level instance.
  36   * - Then there are class instances representing the analysis of each of the sub parts of each variant of the question.
  37   * {@link \core_question\statistics\responses\analysis_for_subpart}.
  38   * - Then within the sub part analysis there are response class analysis
  39   * {@link \core_question\statistics\responses\analysis_for_class}.
  40   * - Then within each class analysis there are analysis for each actual response
  41   * {@link \core_question\statistics\responses\analysis_for_actual_response}.
  42   *
  43   * @package    core_question
  44   * @copyright  2014 The Open University
  45   * @author     James Pratt me@jamiep.org
  46   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  47   */
  48  class analysis_for_subpart {
  49  
  50      /**
  51       * @var analysis_for_class[]
  52       */
  53      protected $responseclasses;
  54  
  55      /**
  56       * Takes an array of possible_responses as returned from {@link \question_type::get_possible_responses()}.
  57       *
  58       * @param \question_possible_response[] $responseclasses as returned from {@link \question_type::get_possible_responses()}.
  59       */
  60      public function __construct(array $responseclasses = null) {
  61          if (is_array($responseclasses)) {
  62              foreach ($responseclasses as $responseclassid => $responseclass) {
  63                  $this->responseclasses[$responseclassid] = new analysis_for_class($responseclass, $responseclassid);
  64              }
  65          } else {
  66              $this->responseclasses = [];
  67          }
  68      }
  69  
  70      /**
  71       * Unique ids for response classes.
  72       *
  73       * @return string[]
  74       */
  75      public function get_response_class_ids() {
  76          return array_keys($this->responseclasses);
  77      }
  78  
  79      /**
  80       * Get the instance of the class handling the analysis of $classid for this sub part.
  81       *
  82       * @param string $classid id for response class.
  83       * @return analysis_for_class
  84       */
  85      public function get_response_class($classid) {
  86          if (!isset($this->responseclasses[$classid])) {
  87              debugging('Unexpected class id ' . $classid . ' encountered.');
  88              $this->responseclasses[$classid] = new analysis_for_class('[Unknown]', $classid);
  89          }
  90          return $this->responseclasses[$classid];
  91  
  92      }
  93  
  94      /**
  95       * Whether there is more than one response class for responses in this question sub part?
  96       *
  97       * @return bool Are there?
  98       */
  99      public function has_multiple_response_classes() {
 100          return count($this->get_response_class_ids()) > 1;
 101      }
 102  
 103      /**
 104       * Count a part of a response.
 105       *
 106       * @param \question_classified_response $subpart
 107       * @param int $try the try number or zero if not keeping track of try number
 108       */
 109      public function count_response($subpart, $try = 0) {
 110          $responseanalysisforclass = $this->get_response_class($subpart->responseclassid);
 111          $responseanalysisforclass->count_response($subpart->response, $subpart->fraction, $try);
 112      }
 113  
 114      /**
 115       * Cache analysis for sub part.
 116       *
 117       * @param \qubaid_condition $qubaids    which question usages have been analysed.
 118       * @param string            $whichtries which tries have been analysed?
 119       * @param int               $questionid which question.
 120       * @param int               $variantno  which variant.
 121       * @param string            $subpartid  which sub part.
 122       * @param int|null          $calculationtime time when the analysis was done. (Defaults to time()).
 123       */
 124      public function cache($qubaids, $whichtries, $questionid, $variantno, $subpartid, $calculationtime = null) {
 125          foreach ($this->get_response_class_ids() as $responseclassid) {
 126              $analysisforclass = $this->get_response_class($responseclassid);
 127              $analysisforclass->cache($qubaids, $whichtries, $questionid, $variantno, $subpartid, $calculationtime);
 128          }
 129      }
 130  
 131      /**
 132       * Has actual responses different to the model response for this class?
 133       *
 134       * @return bool whether this analysis has a response class with more than one
 135       *      different actual response, or if the actual response is different from
 136       *      the model response.
 137       */
 138      public function has_actual_responses() {
 139          foreach ($this->get_response_class_ids() as $responseclassid) {
 140              if ($this->get_response_class($responseclassid)->has_actual_responses()) {
 141                  return true;
 142              }
 143          }
 144          return false;
 145      }
 146  
 147      /**
 148       * What is the highest try number for this sub part?
 149       *
 150       * @return int max tries
 151       */
 152      public function get_maximum_tries() {
 153          $max = 1;
 154          foreach ($this->get_response_class_ids() as $responseclassid) {
 155              $max = max($max, $this->get_response_class($responseclassid)->get_maximum_tries());
 156          }
 157          return $max;
 158      }
 159  }