���ѧۧݧ�ӧ�� �ާ֧ߧ֧էا֧� - ���֧էѧܧ�ڧ��ӧѧ�� - /home3/cpr76684/public_html/responses.tar
���ѧ٧ѧ�
analysis_for_question_all_tries.php 0000644 00000007016 15152126315 0013740 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * This file contains a class to analyse all the responses for multiple tries at a particular question. * * @package core_question * @copyright 2014 Open University * @author Jamie Pratt <me@jamiep.org> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_question\statistics\responses; /** * Analysis for possible responses for parts of a question with multiple submitted responses. * * If the analysis was for a single try it would be handled by {@link \core_question\statistics\responses\analysis_for_question}. * * - There is a separate data structure for each question or sub question's analysis * {@link \core_question\statistics\responses\analysis_for_question} * or {@link \core_question\statistics\responses\analysis_for_question_all_tries}. * - There are separate analysis for each variant in this top level instance. * - Then there are class instances representing the analysis of each of the sub parts of each variant of the question. * {@link \core_question\statistics\responses\analysis_for_subpart}. * - Then within the sub part analysis there are response class analysis * {@link \core_question\statistics\responses\analysis_for_class}. * - Then within each class analysis there are analysis for each actual response * {@link \core_question\statistics\responses\analysis_for_actual_response}. * * @package core_question * @copyright 2014 The Open University * @author James Pratt me@jamiep.org * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class analysis_for_question_all_tries extends analysis_for_question{ /** * Constructor. * * @param int $variantno variant number * @param \array[] $responsepartsforeachtry for question with multiple tries we expect an array with first index being try no * then second index is subpartid and values are \question_classified_response */ public function count_response_parts($variantno, $responsepartsforeachtry) { foreach ($responsepartsforeachtry as $try => $responseparts) { foreach ($responseparts as $subpartid => $responsepart) { $this->get_analysis_for_subpart($variantno, $subpartid)->count_response($responsepart, $try); } } } public function has_multiple_tries_data() { return true; } /** * What is the highest number of tries at this question? * * @return int try number */ public function get_maximum_tries() { $max = 1; foreach ($this->get_variant_nos() as $variantno) { foreach ($this->get_subpart_ids($variantno) as $subpartid) { $max = max($max, $this->get_analysis_for_subpart($variantno, $subpartid)->get_maximum_tries()); } } return $max; } } analysis_for_question.php 0000644 00000021140 15152126315 0011674 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * This file contains the code to analyse all the responses to a particular * question. * * @package core_question * @copyright 2013 Open University * @author Jamie Pratt <me@jamiep.org> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_question\statistics\responses; defined('MOODLE_INTERNAL') || die(); /** * Analysis for possible responses for parts of a question. It is up to a question type designer to decide on how many parts their * question has. See {@link \question_type::get_possible_responses()} and sub classes where the sub parts and response classes are * defined. * * A sub part might represent a sub question embedded in the question for example in a matching question there are * several sub parts. A numeric question with a unit might be divided into two sub parts for the purposes of response analysis * or the question type designer might decide to treat the answer, both the numeric and unit part, * as a whole for the purposes of response analysis. * * - There is a separate data structure for each question or sub question's analysis * {@link \core_question\statistics\responses\analysis_for_question} * or {@link \core_question\statistics\responses\analysis_for_question_all_tries}. * - There are separate analysis for each variant in this top level instance. * - Then there are class instances representing the analysis of each of the sub parts of each variant of the question. * {@link \core_question\statistics\responses\analysis_for_subpart}. * - Then within the sub part analysis there are response class analysis * {@link \core_question\statistics\responses\analysis_for_class}. * - Then within each class analysis there are analysis for each actual response * {@link \core_question\statistics\responses\analysis_for_actual_response}. * * @package core_question * @copyright 2014 The Open University * @author James Pratt me@jamiep.org * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class analysis_for_question { /** * Constructor method. * * @param array[] Two index array, first index is unique string for each sub question part, * the second string index is the 'class' that sub-question part can be classified into. * Value in array is instance of {@link \question_possible_response} * This is the return value from {@link \question_type::get_possible_responses()} * see that method for fuller documentation. */ public function __construct(array $possiblereponses = null) { if ($possiblereponses !== null) { $this->possibleresponses = $possiblereponses; } } /** * @var array[] See description above in constructor method. */ protected $possibleresponses = array(); /** * A multidimensional array whose first index is variant no and second index is subpart id, array contents are of type * {@link analysis_for_subpart}. * * @var array[] */ protected $subparts = array(); /** * Initialise data structure for response analysis of one variant. * * @param int $variantno */ protected function initialise_stats_for_variant($variantno) { $this->subparts[$variantno] = array(); foreach ($this->possibleresponses as $subpartid => $classes) { $this->subparts[$variantno][$subpartid] = new analysis_for_subpart($classes); } } /** * Variant nos found in this question's attempt data. * * @return int[] */ public function get_variant_nos() { return array_keys($this->subparts); } /** * Unique ids for sub parts. * * @param int $variantno * @return string[] */ public function get_subpart_ids($variantno) { return array_keys($this->subparts[$variantno]); } /** * Get the response counts etc. for variant $variantno, question sub part $subpartid. * * Or if there is no recorded analysis yet then initialise the data structure for that part of the analysis and return the * initialised analysis objects. * * @param int $variantno * @param string $subpartid id for sub part. * @return analysis_for_subpart */ public function get_analysis_for_subpart($variantno, $subpartid) { if (!isset($this->subparts[$variantno])) { $this->initialise_stats_for_variant($variantno); } if (!isset($this->subparts[$variantno][$subpartid])) { debugging('Unexpected sub-part id ' . $subpartid . ' encountered.'); $this->subparts[$variantno][$subpartid] = new analysis_for_subpart(); } return $this->subparts[$variantno][$subpartid]; } /** * Used to work out what kind of table is needed to display stats. * * @return bool whether this question has (a subpart with) more than one response class. */ public function has_multiple_response_classes() { foreach ($this->get_variant_nos() as $variantno) { foreach ($this->get_subpart_ids($variantno) as $subpartid) { if ($this->get_analysis_for_subpart($variantno, $subpartid)->has_multiple_response_classes()) { return true; } } } return false; } /** * Used to work out what kind of table is needed to display stats. * * @return bool whether this analysis has more than one subpart. */ public function has_subparts() { foreach ($this->get_variant_nos() as $variantno) { if (count($this->get_subpart_ids($variantno)) > 1) { return true; } } return false; } /** * @return bool Does this response analysis include counts for responses for multiple tries of the question? */ public function has_multiple_tries_data() { return false; } /** * What is the highest number of tries at this question? * * @return int always 1 as this class is for analysing only one try. */ public function get_maximum_tries() { return 1; } /** * Takes an array of {@link \question_classified_response} and adds counts of the responses to the sub parts and classes. * * @param int $variantno * @param \question_classified_response[] $responseparts keys are sub-part id. */ public function count_response_parts($variantno, $responseparts) { foreach ($responseparts as $subpartid => $responsepart) { $this->get_analysis_for_subpart($variantno, $subpartid)->count_response($responsepart); } } /** * @param \qubaid_condition $qubaids which question usages have been analysed. * @param string $whichtries which tries have been analysed? * @param int $questionid which question. */ public function cache($qubaids, $whichtries, $questionid) { foreach ($this->get_variant_nos() as $variantno) { foreach ($this->get_subpart_ids($variantno) as $subpartid) { $analysisforsubpart = $this->get_analysis_for_subpart($variantno, $subpartid); $analysisforsubpart->cache($qubaids, $whichtries, $questionid, $variantno, $subpartid); } } } /** * @return bool whether this analysis has a response class with more than one * different actual response, or if the actual response is different from * the model response. */ public function has_actual_responses() { foreach ($this->get_variant_nos() as $variantno) { foreach ($this->get_subpart_ids($variantno) as $subpartid) { if ($this->get_analysis_for_subpart($variantno, $subpartid)->has_actual_responses()) { return true; } } } return false; } } analyser.php 0000644 00000020252 15152126315 0007075 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * This file contains the code to analyse all the responses to a particular question. * * @package core_question * @copyright 2014 Open University * @author Jamie Pratt <me@jamiep.org> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_question\statistics\responses; defined('MOODLE_INTERNAL') || die(); /** * This class can compute, store and cache the analysis of the responses to a particular question. * * @package core_question * @copyright 2014 The Open University * @author James Pratt me@jamiep.org * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class analyser { /** * @var int When analysing responses and breaking down the count of responses per try, how many columns should we break down * tries into? This is set to 5 columns, any response in a try more than try 5 will be counted in the fifth column. */ const MAX_TRY_COUNTED = 5; /** @var int Time after which responses are automatically reanalysed. */ const TIME_TO_CACHE = 900; // 15 minutes. /** @var object full question data from db. */ protected $questiondata; /** * @var analysis_for_question|analysis_for_question_all_tries */ public $analysis; /** * @var array Two index array first index is unique string for each sub question part, the second string index is the 'class' * that sub-question part can be classified into. * * This is the return value from {@link \question_type::get_possible_responses()} see that method for fuller documentation. */ public $responseclasses = array(); /** * @var bool whether to break down response analysis by variant. This only applies to questions that have variants and is * used to suppress the break down of analysis by variant when there are going to be very many variants. */ protected $breakdownbyvariant; /** * Create a new instance of this class for holding/computing the statistics * for a particular question. * * @param object $questiondata the full question data from the database defining this question. * @param string $whichtries which tries to analyse. */ public function __construct($questiondata, $whichtries = \question_attempt::LAST_TRY) { $this->questiondata = $questiondata; $qtypeobj = \question_bank::get_qtype($this->questiondata->qtype); if ($whichtries != \question_attempt::ALL_TRIES) { $this->analysis = new analysis_for_question($qtypeobj->get_possible_responses($this->questiondata)); } else { $this->analysis = new analysis_for_question_all_tries($qtypeobj->get_possible_responses($this->questiondata)); } $this->breakdownbyvariant = $qtypeobj->break_down_stats_and_response_analysis_by_variant($this->questiondata); } /** * Does the computed analysis have sub parts? * * @return bool whether this analysis has more than one subpart. */ public function has_subparts() { return count($this->responseclasses) > 1; } /** * Does the computed analysis's sub parts have classes? * * @return bool whether this analysis has (a subpart with) more than one response class. */ public function has_response_classes() { foreach ($this->responseclasses as $partclasses) { if (count($partclasses) > 1) { return true; } } return false; } /** * Analyse all the response data for for all the specified attempts at this question. * * @param \qubaid_condition $qubaids which attempts to consider. * @param string $whichtries which tries to analyse. Will be one of * \question_attempt::FIRST_TRY, LAST_TRY or ALL_TRIES. * @return analysis_for_question */ public function calculate($qubaids, $whichtries = \question_attempt::LAST_TRY) { // Load data. $dm = new \question_engine_data_mapper(); $questionattempts = $dm->load_attempts_at_question($this->questiondata->id, $qubaids); // Analyse it. foreach ($questionattempts as $qa) { $responseparts = $qa->classify_response($whichtries); if ($this->breakdownbyvariant) { $this->analysis->count_response_parts($qa->get_variant(), $responseparts); } else { $this->analysis->count_response_parts(1, $responseparts); } } $this->analysis->cache($qubaids, $whichtries, $this->questiondata->id); return $this->analysis; } /** * Retrieve the computed response analysis from the question_response_analysis table. * * @param \qubaid_condition $qubaids load the analysis of which question usages? * @param string $whichtries load the analysis of which tries? * @return analysis_for_question|boolean analysis or false if no cached analysis found. */ public function load_cached($qubaids, $whichtries) { global $DB; $timemodified = time() - self::TIME_TO_CACHE; // Variable name 'analyses' is the plural of 'analysis'. $responseanalyses = $DB->get_records_select('question_response_analysis', 'hashcode = ? AND whichtries = ? AND questionid = ? AND timemodified > ?', array($qubaids->get_hash_code(), $whichtries, $this->questiondata->id, $timemodified)); if (!$responseanalyses) { return false; } $analysisids = array(); foreach ($responseanalyses as $responseanalysis) { $analysisforsubpart = $this->analysis->get_analysis_for_subpart($responseanalysis->variant, $responseanalysis->subqid); $class = $analysisforsubpart->get_response_class($responseanalysis->aid); $class->add_response($responseanalysis->response, $responseanalysis->credit); $analysisids[] = $responseanalysis->id; } list($sql, $params) = $DB->get_in_or_equal($analysisids); $counts = $DB->get_records_select('question_response_count', "analysisid {$sql}", $params); foreach ($counts as $count) { $responseanalysis = $responseanalyses[$count->analysisid]; $analysisforsubpart = $this->analysis->get_analysis_for_subpart($responseanalysis->variant, $responseanalysis->subqid); $class = $analysisforsubpart->get_response_class($responseanalysis->aid); $class->set_response_count($responseanalysis->response, $count->try, $count->rcount); } return $this->analysis; } /** * Find time of non-expired analysis in the database. * * @param \qubaid_condition $qubaids check for the analysis of which question usages? * @param string $whichtries check for the analysis of which tries? * @return integer|boolean Time of cached record that matches this qubaid_condition or false if none found. */ public function get_last_analysed_time($qubaids, $whichtries) { global $DB; $timemodified = time() - self::TIME_TO_CACHE; return $DB->get_field_select('question_response_analysis', 'timemodified', 'hashcode = ? AND whichtries = ? AND questionid = ? AND timemodified > ?', array($qubaids->get_hash_code(), $whichtries, $this->questiondata->id, $timemodified), IGNORE_MULTIPLE); } } analysis_for_actual_response.php 0000644 00000014315 15152126315 0013222 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * @package core_question * @copyright 2013 The Open University * @author James Pratt me@jamiep.org * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_question\statistics\responses; /** * The leafs of the analysis data structure. * * - There is a separate data structure for each question or sub question's analysis * {@link \core_question\statistics\responses\analysis_for_question} * or {@link \core_question\statistics\responses\analysis_for_question_all_tries}. * - There are separate analysis for each variant in this top level instance. * - Then there are class instances representing the analysis of each of the sub parts of each variant of the question. * {@link \core_question\statistics\responses\analysis_for_subpart}. * - Then within the sub part analysis there are response class analysis * {@link \core_question\statistics\responses\analysis_for_class}. * - Then within each class analysis there are analysis for each actual response * {@link \core_question\statistics\responses\analysis_for_actual_response}. * * @package core_question * @copyright 2014 The Open University * @author James Pratt me@jamiep.org * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class analysis_for_actual_response { /** * @var int[] count per try for this response. */ protected $trycount = array(); /** * @var int total count of tries with this response. */ protected $totalcount = 0; /** * @var float grade for this response, normally between 0 and 1. */ protected $fraction; /** * @var string the response as it will be displayed in report. */ protected $response; /** * @param string $response * @param float $fraction */ public function __construct($response, $fraction) { $this->response = $response; $this->fraction = $fraction; } /** * Used to count the occurrences of response sub parts. * * @param int $try the try number, or 0 if only keeping one count, not a count for each try. */ public function increment_count($try = 0) { $this->totalcount++; if ($try != 0) { if ($try > analyser::MAX_TRY_COUNTED) { $try = analyser::MAX_TRY_COUNTED; } if (!isset($this->trycount[$try])) { $this->trycount[$try] = 0; } $this->trycount[$try]++; } } /** * Used to set the count of occurrences of response sub parts, when loading count from cache. * * @param int $try the try number, or 0 if only keeping one count, not a count for each try. * @param int $count */ public function set_count($try, $count) { $this->totalcount = $this->totalcount + $count; $this->trycount[$try] = $count; } /** * Cache analysis for class. * * @param \qubaid_condition $qubaids which question usages have been analysed. * @param string $whichtries which tries have been analysed? * @param int $questionid which question. * @param int $variantno which variant. * @param string $subpartid which sub part is this actual response in? * @param string $responseclassid which response class is this actual response in? */ public function cache($qubaids, $whichtries, $questionid, $variantno, $subpartid, $responseclassid) { global $DB; $row = new \stdClass(); $row->hashcode = $qubaids->get_hash_code(); $row->whichtries = $whichtries; $row->questionid = $questionid; $row->variant = $variantno; $row->subqid = $subpartid; if ($responseclassid === '') { $row->aid = null; } else { $row->aid = $responseclassid; } $row->response = $this->response; $row->credit = $this->fraction; $row->timemodified = time(); $analysisid = $DB->insert_record('question_response_analysis', $row); if ($whichtries === \question_attempt::ALL_TRIES) { foreach ($this->trycount as $try => $count) { $countrow = new \stdClass(); $countrow->try = $try; $countrow->rcount = $count; $countrow->analysisid = $analysisid; $DB->insert_record('question_response_count', $countrow, false); } } else { $countrow = new \stdClass(); $countrow->try = 0; $countrow->rcount = $this->totalcount; $countrow->analysisid = $analysisid; $DB->insert_record('question_response_count', $countrow, false); } } /** * Returns an object with a property for each column of the question response analysis table. * * @param string $partid * @param string $modelresponse * @return object */ public function data_for_question_response_table($partid, $modelresponse) { $rowdata = new \stdClass(); $rowdata->part = $partid; $rowdata->responseclass = $modelresponse; $rowdata->response = $this->response; $rowdata->fraction = $this->fraction; $rowdata->totalcount = $this->totalcount; $rowdata->trycount = $this->trycount; return $rowdata; } /** * What is the highest try number that this response has been seen? * * @return int try number */ public function get_maximum_tries() { return max(array_keys($this->trycount)); } } analysis_for_subpart.php 0000644 00000013626 15152126315 0011517 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * * Data structure to count responses for each of the sub parts of a question. * * @package core_question * @copyright 2014 The Open University * @author James Pratt me@jamiep.org * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_question\statistics\responses; /** * Representing the analysis of each of the sub parts of each variant of the question. * * - There is a separate data structure for each question or sub question's analysis * {@link \core_question\statistics\responses\analysis_for_question} * or {@link \core_question\statistics\responses\analysis_for_question_all_tries}. * - There are separate analysis for each variant in this top level instance. * - Then there are class instances representing the analysis of each of the sub parts of each variant of the question. * {@link \core_question\statistics\responses\analysis_for_subpart}. * - Then within the sub part analysis there are response class analysis * {@link \core_question\statistics\responses\analysis_for_class}. * - Then within each class analysis there are analysis for each actual response * {@link \core_question\statistics\responses\analysis_for_actual_response}. * * @package core_question * @copyright 2014 The Open University * @author James Pratt me@jamiep.org * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class analysis_for_subpart { /** * @var analysis_for_class[] */ protected $responseclasses; /** * Takes an array of possible_responses as returned from {@link \question_type::get_possible_responses()}. * * @param \question_possible_response[] $responseclasses as returned from {@link \question_type::get_possible_responses()}. */ public function __construct(array $responseclasses = null) { if (is_array($responseclasses)) { foreach ($responseclasses as $responseclassid => $responseclass) { $this->responseclasses[$responseclassid] = new analysis_for_class($responseclass, $responseclassid); } } else { $this->responseclasses = []; } } /** * Unique ids for response classes. * * @return string[] */ public function get_response_class_ids() { return array_keys($this->responseclasses); } /** * Get the instance of the class handling the analysis of $classid for this sub part. * * @param string $classid id for response class. * @return analysis_for_class */ public function get_response_class($classid) { if (!isset($this->responseclasses[$classid])) { debugging('Unexpected class id ' . $classid . ' encountered.'); $this->responseclasses[$classid] = new analysis_for_class('[Unknown]', $classid); } return $this->responseclasses[$classid]; } /** * Whether there is more than one response class for responses in this question sub part? * * @return bool Are there? */ public function has_multiple_response_classes() { return count($this->get_response_class_ids()) > 1; } /** * Count a part of a response. * * @param \question_classified_response $subpart * @param int $try the try number or zero if not keeping track of try number */ public function count_response($subpart, $try = 0) { $responseanalysisforclass = $this->get_response_class($subpart->responseclassid); $responseanalysisforclass->count_response($subpart->response, $subpart->fraction, $try); } /** * Cache analysis for sub part. * * @param \qubaid_condition $qubaids which question usages have been analysed. * @param string $whichtries which tries have been analysed? * @param int $questionid which question. * @param int $variantno which variant. * @param string $subpartid which sub part. */ public function cache($qubaids, $whichtries, $questionid, $variantno, $subpartid) { foreach ($this->get_response_class_ids() as $responseclassid) { $analysisforclass = $this->get_response_class($responseclassid); $analysisforclass->cache($qubaids, $whichtries, $questionid, $variantno, $subpartid, $responseclassid); } } /** * Has actual responses different to the model response for this class? * * @return bool whether this analysis has a response class with more than one * different actual response, or if the actual response is different from * the model response. */ public function has_actual_responses() { foreach ($this->get_response_class_ids() as $responseclassid) { if ($this->get_response_class($responseclassid)->has_actual_responses()) { return true; } } return false; } /** * What is the highest try number for this sub part? * * @return int max tries */ public function get_maximum_tries() { $max = 1; foreach ($this->get_response_class_ids() as $responseclassid) { $max = max($max, $this->get_response_class($responseclassid)->get_maximum_tries()); } return $max; } } analysis_for_class.php 0000644 00000017735 15152126315 0011151 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * @package core_question * @copyright 2013 The Open University * @author James Pratt me@jamiep.org * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_question\statistics\responses; /** * Counts a class of responses for this sub part of the question. * * No response is one possible class of response to a question. * * - There is a separate data structure for each question or sub question's analysis * {@link \core_question\statistics\responses\analysis_for_question} * or {@link \core_question\statistics\responses\analysis_for_question_all_tries}. * - There are separate analysis for each variant in this top level instance. * - Then there are class instances representing the analysis of each of the sub parts of each variant of the question. * {@link \core_question\statistics\responses\analysis_for_subpart}. * - Then within the sub part analysis there are response class analysis * {@link \core_question\statistics\responses\analysis_for_class}. * - Then within each class analysis there are analysis for each actual response * {@link \core_question\statistics\responses\analysis_for_actual_response}. * * @package core_question * @copyright 2014 The Open University * @author James Pratt me@jamiep.org * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class analysis_for_class { /** * @var string must be unique for each response class within this sub part. */ protected $responseclassid; /** * @var string represent this class in the response analysis table. */ protected $modelresponse; /** @var string the (partial) credit awarded for this responses. */ protected $fraction; /** @var analysis_for_actual_response[] key is the actual response represented as a string as it will be displayed in report. */ protected $actualresponses = array(); /** * Constructor, just an easy way to set the fields. * * @param \question_possible_response $possibleresponse * @param string $responseclassid */ public function __construct($possibleresponse, $responseclassid) { $this->modelresponse = $possibleresponse->responseclass; $this->fraction = $possibleresponse->fraction; $this->responseclassid = $responseclassid; } /** * Keep a count of a response to this question sub part that falls within this class. * * @param string $actualresponse * @param float|null $fraction * @param int $try * @return \core_question\statistics\responses\analysis_for_actual_response */ public function count_response($actualresponse, $fraction, $try) { if (!isset($this->actualresponses[$actualresponse])) { if ($fraction === null) { $fraction = $this->fraction; } $this->add_response($actualresponse, $fraction); } $this->get_response($actualresponse)->increment_count($try); } /** * Cache analysis for class. * * @param \qubaid_condition $qubaids which question usages have been analysed. * @param string $whichtries which tries have been analysed? * @param int $questionid which question. * @param int $variantno which variant. * @param string $subpartid which sub part. */ public function cache($qubaids, $whichtries, $questionid, $variantno, $subpartid) { foreach ($this->get_responses() as $response) { $analysisforactualresponse = $this->get_response($response); $analysisforactualresponse->cache($qubaids, $whichtries, $questionid, $variantno, $subpartid, $this->responseclassid); } } /** * Add an actual response to the data structure. * * @param string $response A string representing the actual response. * @param float $fraction The fraction of grade awarded for this response. */ public function add_response($response, $fraction) { $this->actualresponses[$response] = new analysis_for_actual_response($response, $fraction); } /** * Used when loading cached counts. * * @param string $response * @param int $try the try number, will be zero if not keeping track of try. * @param int $count the count */ public function set_response_count($response, $try, $count) { $this->actualresponses[$response]->set_count($try, $count); } /** * Are there actual responses to sub parts that where classified into this class? * * @return bool whether this analysis has a response class with more than one * different actual response, or if the actual response is different from * the model response. */ public function has_actual_responses() { $actualresponses = $this->get_responses(); if (count($actualresponses) > 1) { return true; } else if (count($actualresponses) === 1) { $singleactualresponse = reset($actualresponses); return (string)$singleactualresponse !== (string)$this->modelresponse; } return false; } /** * Return the data to display in the response analysis table. * * @param bool $responseclasscolumn * @param string $partid * @return object[] */ public function data_for_question_response_table($responseclasscolumn, $partid) { $return = array(); if (count($this->get_responses()) == 0) { $rowdata = new \stdClass(); $rowdata->part = $partid; $rowdata->responseclass = $this->modelresponse; if (!$responseclasscolumn) { $rowdata->response = $this->modelresponse; } else { $rowdata->response = ''; } $rowdata->fraction = $this->fraction; $rowdata->totalcount = 0; $rowdata->trycount = array(); $return[] = $rowdata; } else { foreach ($this->get_responses() as $actualresponse) { $response = $this->get_response($actualresponse); $return[] = $response->data_for_question_response_table($partid, $this->modelresponse); } } return $return; } /** * What is the highest try number that an actual response of this response class has been seen? * * @return int try number */ public function get_maximum_tries() { $max = 1; foreach ($this->get_responses() as $actualresponse) { $max = max($max, $this->get_response($actualresponse)->get_maximum_tries()); } return $max; } /** * Return array of the actual responses to this sub part that were classified into this class. * * @return string[] the actual responses we are counting tries at. */ protected function get_responses() { return array_keys($this->actualresponses); } /** * Get the data structure used to count the responses that match an actual response within this class of responses. * * @param string $response * @return analysis_for_actual_response the instance for keeping count of tries for $response. */ protected function get_response($response) { return $this->actualresponses[$response]; } }
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | ���֧ߧ֧�ѧ�ڧ� ����ѧߧڧ��: 0 |
proxy
|
phpinfo
|
���ѧ����ۧܧ�