View source
<?php
function quiz_stats_revision_selector_page($quiz) {
$sql = 'SELECT vid FROM {node_revisions} WHERE nid = %d ORDER BY vid';
$res = db_query($sql, $quiz->nid);
$count = 0;
$vids = array();
while ($res_o = db_fetch_object($res)) {
$vids[] = $res_o->vid;
$count++;
}
if ($count < 1) {
return t('Something went wrong. Please try again');
}
elseif ($count == 1) {
drupal_goto("node/{$quiz->nid}/statistics/{$vids[0]}");
}
else {
$content = array();
$content['explanation'] = t('There are !num revisions of this quiz that have been taken.
Different revisions may have different scoring, difficulity and other differences affecting its statistics.
Because of this you have to choose the revision you want to see statistics from.', array(
'!num' => $count,
));
$content['links'] = array();
foreach ($vids as $key => $value) {
$content['links'][] = 'node/' . $quiz->nid . '/statistics/' . $value;
}
return theme('quiz_stats_revision_selector', $content);
}
}
function quiz_stats_get_basic_stats($uid = 0) {
$results = _quiz_get_quizzes($uid);
return empty($results) ? t('No Statistics found.') : theme('quiz_stats_get_basic_stats', $results);
}
function quiz_stats_get_adv_stats($vid, $uid = 0) {
$charts = array();
drupal_add_css(drupal_get_path('module', 'quiz_stats') . '/quiz_stats.css', 'theme');
$charts['takeup'] = _get_date_vs_takeup_count_chart($vid, $uid);
$charts['status'] = _get_quiz_status_chart($vid, $uid);
$charts['top_scorers'] = _get_quiz_top_scorers_chart($vid, $uid);
$charts['grade_range'] = _get_quiz_grade_range_chart($vid, $uid);
return theme('quiz_stats_charts', $charts);
}
function _get_quiz_grade_range_chart($vid, $uid = 0) {
$sql = "SELECT SUM(score >= 0 && score < 20) AS zero_to_twenty,\n SUM(score >= 20 && score < 40) AS twenty_to_fourty,\n SUM(score >= 40 && score < 60) AS fourty_to_sixty,\n SUM(score >= 60 && score < 80) AS sixty_to_eighty,\n SUM(score >= 80 && score <= 100) AS eighty_to_hundred\n FROM {quiz_node_results}\n WHERE vid = %d";
if ($uid != 0) {
$sql .= " AND uid = %d";
}
$range = db_fetch_object(db_query($sql, $vid, $uid));
$count = $range->zero_to_twenty + $range->twenty_to_fourty + $range->fourty_to_sixty + $range->sixty_to_eighty + $range->eighty_to_hundred;
if ($count < 2) {
return FALSE;
}
$chart = '<div id="quiz_top_scorers" class="quiz-stats-chart-space">';
$chart .= theme('quiz_grade_range', $range);
$chart .= '</div>';
return array(
'chart' => $chart,
'title' => t('Distribution'),
'explanation' => t('This chart shows the distribution of the scores on this quiz.'),
);
}
function _get_quiz_top_scorers_chart($vid, $uid = 0) {
$top_scorers = array();
$sql = 'SELECT name, score FROM {quiz_node_results} qnr
LEFT JOIN {users} u ON (u.uid = qnr.uid)
WHERE vid = %d';
if ($uid != 0) {
$sql .= " AND qnr.uid = %d";
}
$sql .= ' ORDER by score DESC';
$results = db_query_range($sql, $vid, $uid, 0, 10);
while ($result = db_fetch_array($results)) {
$key = $result['name'] . '-' . $result['score'];
$top_scorers[$key] = $result;
}
if (count($top_scorers) == 0) {
return FALSE;
}
$chart = '<div id="quiz_top_scorers" class="quiz-stats-chart-space">';
$chart .= theme('quiz_top_scorers', $top_scorers);
$chart .= '</div>';
return array(
'chart' => $chart,
'title' => t('Top scorers'),
'explanation' => t('This chart shows what question takers have the highest scores'),
);
}
function _get_quiz_status_chart($vid, $uid = 0) {
$pass_rate = db_result(db_query("SELECT pass_rate FROM {quiz_node_properties} WHERE vid = %d", $vid));
if (!$pass_rate) {
return;
}
$sql = "SELECT SUM(score > {$pass_rate}) AS no_pass, SUM(score < {$pass_rate}) AS no_fail, SUM(score = 0) AS no_incomplete FROM {quiz_node_results} WHERE vid = %d";
$quiz = db_fetch_array(db_query($sql, intval($vid)));
if ($quiz['no_pass'] + $quiz['no_fail'] + $quiz['no_incomplete'] < 3) {
return FALSE;
}
$chart = '<div id="get_quiz_status_chart" class="quiz-stats-chart-space">';
$chart .= theme('get_quiz_status_chart', $quiz);
$chart .= '</div>';
return array(
'chart' => $chart,
'title' => t('Status'),
'explanation' => t('This chart shows the status for all attempts made to answer this revision of the quiz.'),
);
}
function _get_date_vs_takeup_count_chart($vid, $uid = 0) {
$start = 0;
$end = 30;
$takeup = array();
$sql = "SELECT COUNT(result_id) AS count,\n DATE_FORMAT(FROM_UNIXTIME(time_start), '%Y.%m.%e') AS date\n FROM {quiz_node_results}\n WHERE vid = %d";
$sql_args = array(
$vid,
);
if ($uid != 0) {
$sql .= " AND uid = %d";
$sql_args[] = $uid;
}
$sql .= " GROUP BY date ORDER BY time_start DESC";
$results = db_query_range($sql, $sql_args, $start, $end);
$days = _quiz_get_last_days($end);
$res_o = db_fetch_object($results);
foreach ($days as $date => &$value) {
if ($date == $res_o->date) {
$value->value = $res_o->count;
if ($res_o->count > 0) {
$valid_data = TRUE;
}
$res_o = db_fetch_object($results);
}
}
if (!$valid_data) {
return FALSE;
}
$chart = '<div id="date_vs_takeup_count" class="quiz-stats-chart-space">';
$chart .= theme('date_vs_takeup_count', $days);
$chart .= '</div>';
return array(
'chart' => $chart,
'title' => t('Activity'),
'explanation' => t('This chart shows how many times the quiz has been taken the last !days days.', array(
'!days' => $end,
)),
);
}
function _quiz_get_attempt_count($vid, $uid = 0) {
$sql = "SELECT COUNT(result_id) FROM {quiz_node_results} WHERE nid = %d";
if ($uid != 0) {
$sql .= " AND uid = %d";
}
return db_result(db_query($sql, $vid, $uid));
}
function theme_quiz_grade_range($range) {
$chart_width = 600;
$chart_height = 400;
$chart = array(
'#chart_id' => 'quiz_grade_range',
'#type' => CHART_TYPE_BAR_V_GROUPED,
'#size' => chart_size($chart_width, $chart_height),
'#grid_lines' => chart_grid_lines(10, 10),
'#bar_size' => chart_bar_size(20, 15),
'#adjust_resolution' => TRUE,
);
$chart['#data'][][] = $range->eighty_to_hundred;
$chart['#data'][][] = $range->sixty_to_eighty;
$chart['#data'][][] = $range->fourty_to_sixty;
$chart['#data'][][] = $range->twenty_to_fourty;
$chart['#data'][][] = $range->zero_to_twenty;
$max = max($range->zero_to_twenty, $range->twenty_to_fourty, $range->fourty_to_sixty, $range->sixty_to_eighty, $range->eighty_to_hundred);
$chart['#data_colors'][] = '00ff00';
$chart['#data_colors'][] = '66ff00';
$chart['#data_colors'][] = 'ffff00';
$chart['#data_colors'][] = 'ff6600';
$chart['#data_colors'][] = 'ff0000';
$chart['#mixed_axis_labels'][CHART_AXIS_X_BOTTOM][2][] = chart_mixed_axis_label(t('Quiz Grade Range'), 50);
$chart['#mixed_axis_labels'][CHART_AXIS_Y_LEFT][1][] = chart_mixed_axis_label(t('Attempts'), 100);
$chart['#mixed_axis_labels'][CHART_AXIS_Y_LEFT][0][] = chart_mixed_axis_range_label(0, $max);
$chart['#legends'][] = t('80 to 100 % - ') . $range->eighty_to_hundred;
$chart['#legends'][] = t('60 to 80 % - ') . $range->sixty_to_eighty;
$chart['#legends'][] = t('40 to 60 % - ') . $range->fourty_to_sixty;
$chart['#legends'][] = t('20 to 40 % - ') . $range->twenty_to_fourty;
$chart['#legends'][] = t('0 to 20 % - ') . $range->zero_to_twenty;
return chart_render($chart);
}
function theme_quiz_top_scorers($attendees) {
$chart = array(
'#chart_id' => 'quiz_top_scorers',
'#type' => CHART_TYPE_BAR_V_GROUPED,
'#size' => chart_size(600, 400),
'#grid_lines' => chart_grid_lines(10, 10),
'#bar_size' => chart_bar_size(20, 15),
);
foreach ($attendees as $attendee) {
$chart['#data'][][] = $attendee['score'];
$chart['#data_colors'][] = chart_unique_color(count($chart['#data']));
$chart['#mixed_axis_labels'][CHART_AXIS_X_BOTTOM][2][] = chart_mixed_axis_label(t('Quiz Attendees'), 50);
$chart['#legends'][] = $attendee['name'] . ' ' . $attendee['score'] . ' %';
}
$chart['#mixed_axis_labels'][CHART_AXIS_Y_LEFT][1][] = chart_mixed_axis_label(t('Score') . ' (%)', 100);
$chart['#mixed_axis_labels'][CHART_AXIS_Y_LEFT][0][] = chart_mixed_axis_range_label(0, 100);
return chart_render($chart);
}
function theme_get_quiz_status_chart($quiz) {
$quiz['total'] = $quiz['no_pass'] + $quiz['no_fail'] + $quiz['no_incomplete'];
$chart = array(
'#chart_id' => 'quiz_status_chart',
'#type' => CHART_TYPE_PIE_3D,
'#size' => chart_size(500, 200),
'#adjust_resolution' => TRUE,
);
$chart['#data'] = array(
'pass' => $quiz['no_pass'],
'incomplete' => $quiz['no_incomplete'],
'fail' => $quiz['no_fail'],
);
$chart['#data_colors'] = array(
'pass' => '00ff00',
'incomplete' => 'ffff00',
'fail' => 'ff0000',
);
ini_set('precision', '3');
$chart['#legends'] = array(
'pass' => $quiz['no_pass'] / $quiz['total'] * 100 . t('% pass'),
'incomplete' => $quiz['no_incomplete'] / $quiz['total'] * 100 . t('% incomplete'),
'fail' => $quiz['no_fail'] / $quiz['total'] * 100 . t('% fail'),
);
return chart_render($chart);
}
function theme_date_vs_takeup_count($days) {
$days = array_reverse($days);
$max_count = 0;
$chart = array(
'#chart_id' => 'test_chart',
'#type' => CHART_TYPE_LINE,
'#size' => chart_size(600, 400),
'#grid_lines' => chart_grid_lines(10, 10, 1, 5),
'#adjust_resolution' => TRUE,
);
$interval = 1;
foreach ($days as $date => $obj) {
$count = $obj->value;
$chart['#data'][] = $count;
$x_label = '|';
if ($interval == 7) {
$x_label = chart_mixed_axis_label(format_date($obj->timestamp, 'custom', 'd M'));
$interval = 0;
}
$chart['#mixed_axis_labels'][CHART_AXIS_X_BOTTOM][0][] = $x_label;
$interval++;
$max_count = $max_count > $count ? $max_count : $count;
}
$chart['#mixed_axis_labels'][CHART_AXIS_Y_LEFT][0][] = chart_mixed_axis_range_label(0, $max_count);
$chart['#mixed_axis_labels'][CHART_AXIS_Y_LEFT][1] = array(
'|',
chart_mixed_axis_label(t('Attempts')),
);
$chart['#mixed_axis_labels'][CHART_AXIS_X_BOTTOM][1] = array(
'|',
chart_mixed_axis_label(t('Date')),
'|',
);
return chart_render($chart);
}
function theme_quiz_stats_get_basic_stats($results = array()) {
if (empty($results)) {
return '<p>' . t('No questions were found.') . '</p>';
}
$header = $rows = array();
$header = array(
'title' => t('Quiz'),
'creator' => t('Author'),
'created' => t('Created'),
);
if (user_access('access author stats')) {
$header['questions_count'] = t('Questions');
$header['attempt_count'] = t('Attempts');
}
$p = drupal_get_path('module', 'quiz_stats');
$chart_icon = theme('image', "{$p}/chart.png", t('Charts'), t('See charts'));
foreach ($results as $result) {
$title_link = user_access('access author stats') ? 'node/' . $result['nid'] . '/statistics' : 'user/' . arg(1) . '/stats/';
$row = array(
'title' => l($chart_icon . ' ' . $result['title'], $title_link, array(
'html' => TRUE,
)),
'creator' => l($result['name'], 'user/' . $result['uid']),
'created' => format_date($result['created'], 'small'),
);
if (user_access('access author stats')) {
$row['questions_count'] = quiz_get_number_of_questions($result['vid']);
$row['attempt_count'] = _quiz_get_attempt_count($result['nid']);
}
$rows[] = $row;
}
module_load_include('inc', 'quiz', 'quiz.pages');
$cc = '<em>' . t('Chart icon from !url', array(
'!url' => 'pinvoke.com',
)) . '</em>';
return theme('table', $header, $rows, array(
'id' => 'tablesorter',
)) . $cc;
}
function _quiz_get_last_days($num_days) {
$to_return = array();
$now = time();
$one_day = 86400;
for ($i = 0; $i < $num_days; $i++) {
$timestamp = $now - $one_day * $i;
$to_add = new stdClass();
$to_add->timestamp = $timestamp;
$to_add->value = '0';
$to_return[date('Y.m.j', $timestamp)] = $to_add;
}
return $to_return;
}