Exercises: Add new exercise stats reports BT#17785 WIP

pull/3564/head
Julio Montoya 5 years ago
parent ba82a946d3
commit c95f6d7d66
  1. 58
      main/inc/lib/exercise.lib.php
  2. 18
      main/mySpace/course.php
  3. 162
      main/mySpace/question_stats_global.php
  4. 163
      main/mySpace/question_stats_global_detail.php

@ -5654,7 +5654,7 @@ EOT;
return $total;
}
public static function getWrongQuestionResults($courseId, $exerciseId, $limit = 10)
public static function getWrongQuestionResults($courseId, $exerciseId, $sessionId = 0, $limit = 10)
{
$courseId = (int) $courseId;
$exerciseId = (int) $exerciseId;
@ -5664,6 +5664,11 @@ EOT;
$attemptTable = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
$trackTable = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
$sessionCondition = '';
if (!empty($sessionId)) {
$sessionCondition = api_get_session_condition($sessionId, true, false, 'te.session_id');
}
$sql = "SELECT q.question, question_id, count(q.iid) count
FROM $attemptTable t
INNER JOIN $questionTable q
@ -5675,6 +5680,7 @@ EOT;
t.marks != q.ponderation AND
exe_exo_id = $exerciseId AND
status != 'incomplete'
$sessionCondition
GROUP BY q.iid
ORDER BY count DESC
LIMIT $limit
@ -5684,4 +5690,54 @@ EOT;
return Database::store_result($result, 'ASSOC');
}
public static function getExerciseResultsCount($type, $courseId, $exerciseId, $sessionId = 0)
{
$courseId = (int) $courseId;
$exerciseId = (int) $exerciseId;
$trackTable = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
$sessionCondition = '';
if (!empty($sessionId)) {
$sessionCondition = api_get_session_condition($sessionId, true, false, 'te.session_id');
}
$selectCount = 'count(DISTINCT te.exe_id)';
$scoreCondition = '';
switch ($type) {
case 'correct_student':
$selectCount = 'count(DISTINCT te.exe_user_id)';
$scoreCondition = ' AND exe_result = exe_weighting ';
break;
case 'wrong_student':
$selectCount = 'count(DISTINCT te.exe_user_id)';
$scoreCondition = ' AND exe_result != exe_weighting ';
break;
case 'correct':
$scoreCondition = ' AND exe_result = exe_weighting ';
break;
case 'wrong':
$scoreCondition = ' AND exe_result != exe_weighting ';
break;
}
$sql = "SELECT $selectCount count
FROM $trackTable te
WHERE
c_id = $courseId AND
exe_exo_id = $exerciseId AND
status != 'incomplete'
$scoreCondition
$sessionCondition
";
$result = Database::query($sql);
$totalRow = Database::fetch_array($result, 'ASSOC');
$total = 0;
if ($totalRow) {
$total = (int) $totalRow['count'];
}
return $total;
}
}

@ -102,11 +102,23 @@ if (api_is_platform_admin(true, true)) {
);
$menu_items[] = Display::url(
Display::return_icon('session.png', get_lang('Sessions'), [], ICON_SIZE_MEDIUM),
'session.php'
api_get_path(WEB_CODE_PATH).'mySpace/session.php'
);
$menu_items[] = Display::url(
get_lang('QuestionStats'),
api_get_path(WEB_CODE_PATH).'mySpace/question_stats_global.php'
);
$menu_items[] = Display::url(
get_lang('QuestionStatsDetail'),
api_get_path(WEB_CODE_PATH).'mySpace/question_stats_global_detail.php'
);
if (api_can_login_as($user_id)) {
$link = '<a href="'.api_get_path(WEB_CODE_PATH).'admin/user_list.php?action=login_as&amp;user_id='.$user_id.'&amp;sec_token='.Security::get_existing_token().'">'.
Display::return_icon('login_as.png', get_lang('LoginAs'), null, ICON_SIZE_MEDIUM).'</a>&nbsp;&nbsp;';
$link = '<a
href="'.api_get_path(WEB_CODE_PATH).'admin/user_list.php?action=login_as&amp;user_id='.$user_id.'&amp;sec_token='.Security::get_existing_token().'">'.
Display::return_icon('login_as.png', get_lang('LoginAs'), null, ICON_SIZE_MEDIUM).'</a>&nbsp;&nbsp;';
$menu_items[] = $link;
}
}

@ -0,0 +1,162 @@
<?php
/* For licensing terms, see /license.txt */
$cidReset = true;
require_once __DIR__.'/../inc/global.inc.php';
$this_section = SECTION_TRACKING;
api_block_anonymous_users();
$allowToTrack = api_is_platform_admin(true, true) || api_is_teacher();
if (!$allowToTrack) {
api_not_allowed(true);
}
$interbreadcrumb[] = ["url" => "index.php", "name" => get_lang('MySpace')];
$courseIdList = isset($_REQUEST['courses']) ? $_REQUEST['courses'] : [];
$exercises = isset($_REQUEST['exercises']) ? $_REQUEST['exercises'] : [];
$courseOptions = [];
$exercisesList = [];
$selectedExercises = [];
if (!empty($courseIdList)) {
foreach ($courseIdList as $courseId) {
$courseInfo = api_get_course_info_by_id($courseId);
$courseExerciseList = ExerciseLib::get_all_exercises(
$courseInfo,
0,
false,
null,
false,
3
);
if (!empty($courseExerciseList)) {
foreach ($courseExerciseList as $exercise) {
$exerciseId = $exercise['iid'];
if (in_array( $exerciseId, $exercises)) {
$selectedExercises[$courseId][] = $exerciseId;
}
}
$exercisesList += array_column($courseExerciseList, 'title', 'iid');
}
$courseOptions[$courseId] = $courseInfo['name'];
}
}
$exercisesList = array_unique($exercisesList);
$form = new FormValidator('search_form', 'GET', api_get_self());
$form->addSelectAjax(
'courses',
get_lang('Course'),
$courseOptions,
[
'url' => api_get_path(WEB_AJAX_PATH).'course.ajax.php?a=search_course',
'multiple' => true
]
);
if (!empty($courseIdList)) {
$form->addSelect(
'exercises',
get_lang('Exercise'),
$exercisesList,
[
'multiple' => true,
]
);
}
$form->setDefaults(['course_id_list' => array_keys($courseOptions)]);
$form->addButtonSearch(get_lang('Search'));
$tableContent = '';
if ($form->validate()) {
$headers = [
get_lang('Course'),
get_lang('Exercise'),
get_lang('Question'),
get_lang('WrongAnswer').' / '.get_lang('Total'),
'%',
];
/*$table = new HTML_Table(['class' => 'table table-hover table-striped']);
$row = 0;
$column = 0;
foreach ($headers as $header) {
$table->setHeaderContents($row, $column, $header);
$column++;
}
$row++;*/
$scoreDisplay = new ScoreDisplay();
$exercises = $form->getSubmitValue('exercises');
if ($exercises) {
$orderedData = [];
foreach ($selectedExercises as $courseId => $exerciseList) {
foreach ($exerciseList as $exerciseId) {
$questions = ExerciseLib::getWrongQuestionResults($courseId, $exerciseId, null,10);
foreach ($questions as $data) {
$questionId = (int) $data['question_id'];
$total = ExerciseLib::getTotalQuestionAnswered($courseId, $exerciseId, $questionId);
/*$column = 0;
$table->setCellContents($row, $column++, $courseOptions[$courseId]);
$table->setCellContents($row, $column++, $exercisesList[$exerciseId]);
$table->setCellContents($row, $column++, $data['question']);
$table->setCellContents($row, $column++, $data['count'].' / '.$total);
$percentage = $data['count']/$total;
$table->setCellContents(
$row,
$column++,
$scoreDisplay->display_score([$data['count'], $total], SCORE_AVERAGE)
);
$row++;*/
$orderedData[] = [
$courseOptions[$courseId],
$exercisesList[$exerciseId],
$data['question'],
$data['count'].' / '.$total,
$scoreDisplay->display_score([$data['count'], $total], SCORE_AVERAGE),
];
}
}
}
$table = new SortableTableFromArray(
$orderedData,
1,
20,
'question_tracking'
);
$table->column = 4;
$column = 0;
foreach ($headers as $header) {
$table->set_header($column, $header, false);
$column++;
}
$tableContent = $table->return_table();
}
}
$nameTools = get_lang('ExerciseManagement');
$htmlHeadXtra[] = '<script>
$(function() {
$("#search_form").submit();
$("#search_form_courses").on("change", function (e) {
$("#search_form_exercises").parent().parent().parent().hide();
$("#search_form_exercises").each(function() {
$(this).remove();
});
});
});
</script>';
Display::display_header($nameTools, get_lang('Exercise'));
$form->display();
echo $tableContent;
Display::display_footer();

@ -0,0 +1,163 @@
<?php
/* For licensing terms, see /license.txt */
$cidReset = true;
require_once __DIR__.'/../inc/global.inc.php';
$this_section = SECTION_TRACKING;
api_block_anonymous_users();
$allowToTrack = api_is_platform_admin(true, true) || api_is_teacher();
if (!$allowToTrack) {
api_not_allowed(true);
}
$interbreadcrumb[] = ["url" => "index.php", "name" => get_lang('MySpace')];
$courseIdList = isset($_REQUEST['courses']) ? $_REQUEST['courses'] : [];
$exercises = isset($_REQUEST['exercises']) ? $_REQUEST['exercises'] : [];
$courseOptions = [];
$exercisesList = [];
$selectedExercises = [];
if (!empty($courseIdList)) {
foreach ($courseIdList as $courseId) {
$courseInfo = api_get_course_info_by_id($courseId);
$courseExerciseList = ExerciseLib::get_all_exercises(
$courseInfo,
0,
false,
null,
false,
3
);
if (!empty($courseExerciseList)) {
foreach ($courseExerciseList as $exercise) {
$exerciseId = $exercise['iid'];
if (in_array( $exerciseId, $exercises)) {
$selectedExercises[$courseId][] = $exerciseId;
}
}
$exercisesList += array_column($courseExerciseList, 'title', 'iid');
}
$courseOptions[$courseId] = $courseInfo['name'];
}
}
$exercisesList = array_unique($exercisesList);
$form = new FormValidator('search_form', 'GET', api_get_self());
$form->addSelectAjax(
'courses',
get_lang('Course'),
$courseOptions,
[
'url' => api_get_path(WEB_AJAX_PATH).'course.ajax.php?a=search_course',
'multiple' => true
]
);
if (!empty($courseIdList)) {
$form->addSelect(
'exercises',
get_lang('Exercise'),
$exercisesList,
[
'multiple' => true,
]
);
}
$form->setDefaults(['course_id_list' => array_keys($courseOptions)]);
$form->addButtonSearch(get_lang('Search'));
$tableContent = '';
if ($form->validate()) {
$headers = [
get_lang('Session'),
get_lang('CorrectAttempts'),
get_lang('WrongAttempts'),
get_lang('StudentWithCorrectAnswers'),
get_lang('StudentWithWrongAnswers')
];
$scoreDisplay = new ScoreDisplay();
$exercises = $form->getSubmitValue('exercises');
if ($exercises) {
foreach ($selectedExercises as $courseId => $exerciseList) {
$sessions = SessionManager::get_session_by_course($courseId );
$courseTitle = $courseOptions[$courseId];
foreach ($exerciseList as $exerciseId) {
$exerciseTitle = $exercisesList[$exerciseId];
$tableContent .= Display::page_subheader2($courseTitle.' - '.$exerciseTitle);
$orderedData = [];
foreach ($sessions as $session) {
$sessionId = $session['id'];
$correctCount = ExerciseLib::getExerciseResultsCount('correct', $courseId, $exerciseId, $sessionId);
$wrongCount = ExerciseLib::getExerciseResultsCount('wrong', $courseId, $exerciseId, $sessionId);
$correctCountStudent = ExerciseLib::getExerciseResultsCount(
'correct_student',
$courseId,
$exerciseId,
$sessionId
);
$wrongCountStudent = ExerciseLib::getExerciseResultsCount(
'wrong_student',
$courseId,
$exerciseId,
$sessionId
);
$questions = ExerciseLib::getWrongQuestionResults($courseId, $exerciseId, $sessionId, 10);
$orderedData[] = [
$session['name'],
$correctCount,
$wrongCount,
$correctCountStudent,
$wrongCountStudent
];
}
$table = new SortableTableFromArray(
$orderedData,
1,
20,
uniqid('question_tracking_')
);
$column = 0;
foreach ($headers as $header) {
$table->set_header($column, $header, false);
$column++;
}
$tableContent .= $table->return_table();
}
}
}
}
$nameTools = get_lang('ExerciseManagement');
$htmlHeadXtra[] = '<script>
$(function() {
$("#search_form").submit();
$("#search_form_courses").on("change", function (e) {
$("#search_form_exercises").parent().parent().parent().hide();
$("#search_form_exercises").each(function() {
$(this).remove();
});
});
});
</script>';
Display::display_header($nameTools, get_lang('Exercise'));
$form->display();
echo $tableContent;
Display::display_footer();
Loading…
Cancel
Save