MDL-55026 quiz_overview: Convert chart to the new library

Part of MDL-54987 epic.
This commit is contained in:
Frederic Massart 2016-06-27 15:13:53 +08:00 committed by Dan Poltawski
parent 601da0e693
commit ec882623f3
4 changed files with 120 additions and 112 deletions

View File

@ -1233,6 +1233,17 @@ class mod_quiz_renderer extends plugin_renderer_base {
return html_writer::link($url, $summary);
}
/**
* Outputs a chart.
*
* @param \core\chart_base $chart The chart.
* @param string $title The title to display above the graph.
* @return string HTML fragment for the graph.
*/
public function chart(\core\chart_base $chart, $title) {
return $this->heading($title, 3) . html_writer::tag('div', $this->render($chart), array('class' => 'graph'));
}
/**
* Output a graph, or a message saying that GD is required.
* @param moodle_url $url the URL of the graph.

View File

@ -20,110 +20,12 @@
* @package quiz_overview
* @copyright 2008 Jamie Pratt
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @deprecated since Moodle 3.2
*/
require_once(__DIR__ . '/../../../../config.php');
require_once($CFG->libdir . '/graphlib.php');
require_once($CFG->dirroot . '/mod/quiz/locallib.php');
require_once($CFG->dirroot . '/mod/quiz/report/reportlib.php');
require_once($CFG->libdir . '/filelib.php');
$quizid = required_param('id', PARAM_INT);
$groupid = optional_param('groupid', 0, PARAM_INT);
$quiz = $DB->get_record('quiz', array('id' => $quizid));
$course = $DB->get_record('course', array('id' => $quiz->course));
$cm = get_coursemodule_from_instance('quiz', $quizid);
require_login($course, false, $cm);
$modcontext = context_module::instance($cm->id);
require_capability('mod/quiz:viewreports', $modcontext);
if ($groupid && $groupmode = groups_get_activity_groupmode($cm)) {
// Groups are being used.
$groups = groups_get_activity_allowed_groups($cm);
if (!array_key_exists($groupid, $groups)) {
print_error('errorinvalidgroup', 'group', null, $groupid);
}
$group = $groups[$groupid];
$groupusers = get_users_by_capability($modcontext,
array('mod/quiz:reviewmyattempts', 'mod/quiz:attempt'),
'', '', '', '', $group->id, '', false);
if (!$groupusers) {
print_error('nostudentsingroup');
}
$groupusers = array_keys($groupusers);
} else {
$groupusers = array();
}
$line = new graph(800, 600);
$line->parameter['title'] = '';
$line->parameter['y_label_left'] = get_string('participants');
$line->parameter['x_label'] = get_string('grade');
$line->parameter['y_label_angle'] = 90;
$line->parameter['x_label_angle'] = 0;
$line->parameter['x_axis_angle'] = 60;
// The following two lines seem to silence notice warnings from graphlib.php.
$line->y_tick_labels = null;
$line->offset_relation = null;
// We will make size > 1 to get an overlap effect when showing groups.
$line->parameter['bar_size'] = 1;
// Don't forget to increase spacing so that graph doesn't become one big block of colour.
$line->parameter['bar_spacing'] = 10;
// Pick a sensible number of bands depending on quiz maximum grade.
$bands = $quiz->grade;
while ($bands > 20 || $bands <= 10) {
if ($bands > 50) {
$bands /= 5;
} else if ($bands > 20) {
$bands /= 2;
}
if ($bands < 4) {
$bands *= 5;
} else if ($bands <= 10) {
$bands *= 2;
}
}
// See MDL-34589. Using doubles as array keys causes problems in PHP 5.4,
// hence the explicit cast to int.
$bands = (int) ceil($bands);
$bandwidth = $quiz->grade / $bands;
$bandlabels = array();
for ($i = 1; $i <= $bands; $i++) {
$bandlabels[] = quiz_format_grade($quiz, ($i - 1) * $bandwidth) . ' - ' .
quiz_format_grade($quiz, $i * $bandwidth);
}
$line->x_data = $bandlabels;
$line->y_format['allusers'] = array(
'colour' => 'red',
'bar' => 'fill',
'shadow_offset' => 1,
'legend' => get_string('allparticipants')
);
$line->y_data['allusers'] = quiz_report_grade_bands($bandwidth, $bands, $quizid, $groupusers);
$line->y_order = array('allusers');
$ymax = max($line->y_data['allusers']);
$line->parameter['y_min_left'] = 0;
$line->parameter['y_max_left'] = $ymax;
$line->parameter['y_decimal_left'] = 0;
// Pick a sensible number of gridlines depending on max value on graph.
$gridlines = $ymax;
while ($gridlines >= 10) {
if ($gridlines >= 50) {
$gridlines /= 5;
} else {
$gridlines /= 2;
}
}
$line->parameter['y_axis_gridlines'] = $gridlines + 1;
$line->draw();
debugging('This way of generating the chart is deprecated, refer to quiz_overview_report::display().', DEBUG_DEVELOPER);
send_file_not_found();

View File

@ -232,24 +232,25 @@ class quiz_overview_report extends quiz_attempts_report {
if (!$table->is_downloading() && $options->usercanseegrades) {
$output = $PAGE->get_renderer('mod_quiz');
list($bands, $bandwidth) = self::get_bands_count_and_width($quiz);
$labels = self::get_bands_labels($bands, $bandwidth, $quiz);
if ($currentgroup && $groupstudents) {
list($usql, $params) = $DB->get_in_or_equal($groupstudents);
$params[] = $quiz->id;
if ($DB->record_exists_select('quiz_grades', "userid $usql AND quiz = ?",
$params)) {
$imageurl = new moodle_url('/mod/quiz/report/overview/overviewgraph.php',
array('id' => $quiz->id, 'groupid' => $currentgroup));
$graphname = get_string('overviewreportgraphgroup', 'quiz_overview',
groups_get_group_name($currentgroup));
echo $output->graph($imageurl, $graphname);
if ($DB->record_exists_select('quiz_grades', "userid $usql AND quiz = ?", $params)) {
$data = quiz_report_grade_bands($bandwidth, $bands, $quiz->id, $groupstudents);
$chart = self::get_chart($labels, $data);
$graphname = get_string('overviewreportgraphgroup', 'quiz_overview', groups_get_group_name($currentgroup));
echo $output->chart($chart, $graphname);
}
}
if ($DB->record_exists('quiz_grades', array('quiz'=> $quiz->id))) {
$imageurl = new moodle_url('/mod/quiz/report/overview/overviewgraph.php',
array('id' => $quiz->id));
$data = quiz_report_grade_bands($bandwidth, $bands, $quiz->id, []);
$chart = self::get_chart($labels, $data);
$graphname = get_string('overviewreportgraph', 'quiz_overview');
echo $output->graph($imageurl, $graphname);
echo $output->chart($chart, $graphname);
}
}
return true;
@ -566,4 +567,70 @@ class quiz_overview_report extends quiz_attempts_report {
quiz_update_all_final_grades($quiz);
quiz_update_grades($quiz);
}
/**
* Get the bands configuration for the quiz.
*
* This returns the configuration for having between 11 and 20 bars in
* a chart based on the maximum grade to be given on a quiz. The width of
* a band is the number of grade points it encapsulates.
*
* @param object $quiz The quiz object.
* @return array Contains the number of bands, and their width.
*/
public static function get_bands_count_and_width($quiz) {
$bands = $quiz->grade;
while ($bands > 20 || $bands <= 10) {
if ($bands > 50) {
$bands /= 5;
} else if ($bands > 20) {
$bands /= 2;
}
if ($bands < 4) {
$bands *= 5;
} else if ($bands <= 10) {
$bands *= 2;
}
}
// See MDL-34589. Using doubles as array keys causes problems in PHP 5.4, hence the explicit cast to int.
$bands = (int) ceil($bands);
return [$bands, $quiz->grade / $bands];
}
/**
* Get the bands labels.
*
* @param int $bands The number of bands.
* @param int $bandwidth The band width.
* @param object $quiz The quiz object.
* @return string[] The labels.
*/
public static function get_bands_labels($bands, $bandwidth, $quiz) {
$bandlabels = [];
for ($i = 1; $i <= $bands; $i++) {
$bandlabels[] = quiz_format_grade($quiz, ($i - 1) * $bandwidth) . ' - ' . quiz_format_grade($quiz, $i * $bandwidth);
}
return $bandlabels;
}
/**
* Get a chart.
*
* @param string[] $labels Chart labels.
* @param int[] $data The data.
* @return \core\chart_base
*/
protected static function get_chart($labels, $data) {
$chart = new \core\chart_bar();
$chart->set_labels($labels);
$chart->get_xaxis(0, true)->set_label(get_string('grade'));
$yaxis = $chart->get_yaxis(0, true);
$yaxis->set_label(get_string('participants'));
$yaxis->set_stepsize(max(1, round(max($data) / 10)));
$series = new \core\chart_series(get_string('participants'), $data);
$chart->add_series($series);
return $chart;
}
}

View File

@ -126,4 +126,32 @@ class quiz_overview_report_testcase extends advanced_testcase {
$this->assertArrayHasKey($student3->id . '#0', $table->rawdata);
$this->assertEquals(0, $table->rawdata[$student3->id . '#0']->gradedattempt);
}
/**
* Bands provider.
* @return array
*/
public function get_bands_count_and_width_provider() {
return [
[10, [20, .5]],
[20, [20, 1]],
[30, [15, 2]],
// TODO MDL-55068 Handle bands better when grade is 50.
// [50, [10, 5]],
[100, [20, 5]],
[200, [20, 10]],
];
}
/**
* Test bands.
* @dataProvider get_bands_count_and_width_provider
*/
public function test_get_bands_count_and_width($grade, $expected) {
$this->resetAfterTest(true);
$quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz');
$quiz = $quizgenerator->create_instance(['course' => SITEID, 'grade' => $grade]);
$this->assertEquals($expected, quiz_overview_report::get_bands_count_and_width($quiz));
}
}