/** * Saves the mean/median of a question on a paper. * @param int $paperID - The ID of the paper we are dealing with. * @param array $q_medians - Array containing the statistics to be saved. */ public function save_median_question_marks($paperID, $q_medians) { $this->db->autocommit(false); $result = $this->db->prepare("REPLACE INTO cache_median_question_marks (paperID, questionID, median, mean) VALUES (?, ?, ?, ?)"); foreach ($q_medians as $q_id => $median_array) { $median = MathsUtils::median($median_array); $mean = MathsUtils::mean($median_array); $result->bind_param('iidd', $paperID, $q_id, $median, $mean); $result->execute(); } $result->close(); $this->db->commit(); $this->db->autocommit(true); }
/** * Creates an array of basic statistics on the cohort performance. */ public function generate_stats() { $configObject = Config::get_instance(); $percent_decimals = $configObject->get('percent_decimals'); // Generate summary statistics. $this->set_user_no(); $mark_total = 0; $percent_total = 0; $this->stats['sum_of_marks'] = 0; $this->stats['out_of_range'] = 0; $this->stats['completed_no'] = 0; $this->stats['failures'] = 0; $this->stats['passes'] = 0; $this->stats['honours'] = 0; $this->stats['total_time'] = 0; $this->stats['max_mark'] = 0; $this->stats['min_mark'] = 9999; $this->stats['max_percent'] = 0; $this->stats['min_percent'] = 100; $median_mark_array = array(); $median_percent_array = array(); $marks_data = array(); for ($i = 0; $i < $this->user_no; $i++) { if (isset($this->user_results[$i]['percent']) and $this->user_results[$i]['questions'] >= $this->question_no and $this->user_results[$i]['visible']) { $this->stats['completed_no']++; $median_mark_array[] = round($this->user_results[$i]['mark'], $percent_decimals); $median_percent_array[] = round($this->user_results[$i]['percent'], $percent_decimals); $mark_total += round($this->user_results[$i]['mark'], $percent_decimals); $percent_total += round($this->user_results[$i]['percent'], $percent_decimals); // Round to the precision being displayed on screen. } if (isset($this->user_results[$i]['mark']) and $this->user_results[$i]['visible']) { $tmp_mark = round($this->user_results[$i]['mark'], $percent_decimals); $tmp_percent = round($this->user_results[$i]['percent'], $percent_decimals); $marks_data[] = $tmp_percent; if ($tmp_percent < $this->pass_mark) { $this->stats['failures']++; } if ($tmp_percent < $this->stats['min_percent']) { $this->stats['min_percent'] = $tmp_percent; } if ($tmp_percent > $this->stats['max_percent']) { $this->stats['max_percent'] = $tmp_percent; } if ($tmp_percent >= $this->pass_mark and $tmp_percent < $this->distinction_mark) { $this->stats['passes']++; } if ($tmp_percent >= $this->distinction_mark) { $this->stats['honours']++; } if ($tmp_mark < $this->stats['min_mark']) { $this->stats['min_mark'] = $tmp_mark; } if ($tmp_mark > $this->stats['max_mark']) { $this->stats['max_mark'] = $tmp_mark; } $this->stats['sum_of_marks'] += $tmp_mark; } if ($this->user_results[$i]['visible']) { $this->stats['total_time'] += $this->user_results[$i]['duration']; } else { $this->stats['out_of_range']++; } } if ($this->stats['min_mark'] == 9999) { $this->stats['min_mark'] = 0; } // Reset back to zero if still on default. $this->stats['range'] = $this->stats['max_mark'] - $this->stats['min_mark']; $this->stats['range_percent'] = $this->stats['max_percent'] - $this->stats['min_percent']; // Calculate StdDev. $xmean_total = 0; $xmean_percent_total = 0; for ($i = 0; $i < $this->user_no; $i++) { if (isset($this->user_results[$i]['questions']) and $this->user_results[$i]['questions'] >= $this->question_no and $this->user_results[$i]['visible'] and $this->stats['completed_no'] > 0) { $tmp_percent = round($this->user_results[$i]['percent'], $percent_decimals); $xmean_total += ($this->user_results[$i]['mark'] - $mark_total / $this->stats['completed_no']) * ($this->user_results[$i]['mark'] - $mark_total / $this->stats['completed_no']); $xmean_percent_total += ($tmp_percent - $percent_total / $this->stats['completed_no']) * ($tmp_percent - $percent_total / $this->stats['completed_no']); } } if ($this->stats['completed_no'] > 1) { $this->stats['stddev_mark'] = sqrt($xmean_total / ($this->stats['completed_no'] - 1)); $this->stats['stddev_percent'] = sqrt($xmean_percent_total / ($this->stats['completed_no'] - 1)); } else { $this->stats['stddev_mark'] = 0; $this->stats['stddev_percent'] = 0; } if ($this->stats['completed_no'] > 0) { $this->stats['mean_mark'] = $mark_total / $this->stats['completed_no']; $this->stats['mean_percent'] = $percent_total / $this->stats['completed_no']; $this->stats['median_mark'] = MathsUtils::median($median_mark_array); $this->stats['median_percent'] = MathsUtils::median($median_percent_array); } else { $this->stats['mean_mark'] = 0; $this->stats['mean_percent'] = 0; $this->stats['median_mark'] = 0; $this->stats['median_percent'] = 0; } $this->stats['q1'] = MathsUtils::percentile($marks_data, 0.75); $this->stats['q2'] = MathsUtils::percentile($marks_data, 0.5); $this->stats['q3'] = MathsUtils::percentile($marks_data, 0.25); for ($i = 1; $i < 10; $i++) { $this->stats["decile{$i}"] = MathsUtils::percentile($marks_data, $i / 10); } }