Internal: Improve exercises internal code

pull/5076/head
BorjaSanchezBeezNest 2 years ago committed by Yannick Warnier
parent a9fdacaa7b
commit 188f982edc
  1. 127
      public/main/exercise/stats.php
  2. 193
      public/main/inc/lib/exercise.lib.php
  3. 6
      translations/main.pot
  4. 6
      translations/messages.en.po
  5. 15
      translations/messages.es.po

@ -54,7 +54,7 @@ $data = [];
$headers = [
get_lang('Question'),
get_lang('Question type'),
get_lang('Number of learners who selected it'),
get_lang('Number of times the question was answered'),
get_lang('Lowest score'),
get_lang('Average score'),
get_lang('Highest score'),
@ -65,7 +65,7 @@ if (!empty($question_list)) {
foreach ($question_list as $question_id) {
$questionObj = Question::read($question_id);
$exercise_stats = ExerciseLib::get_student_stats_by_question(
$exercise_stats = ExerciseLib::getStudentStatsByQuestion(
$question_id,
$exerciseId,
$courseCode,
@ -73,26 +73,16 @@ if (!empty($question_list)) {
true
);
$count_users = ExerciseLib::get_number_students_question_with_answer_count(
$question_id,
$exerciseId,
$courseCode,
$sessionId,
$questionObj->type
);
$data[$question_id]['name'] = cut($questionObj->question, 100);
$data[$question_id]['type'] = $questionObj->getExplanation();
$percentage = 0;
if ($count_students) {
$percentage = $count_users / $count_students * 100;
}
$data[$question_id]['students_who_try_exercise'] = Display::bar_progress(
$percentage,
false,
$count_users.' / '.$count_students
$totalTimesQuestionAnswered = ExerciseLib::getTotalQuestionAnswered(
$questionObj->course['id'],
$exerciseId,
$question_id,
true
);
$data[$question_id]['students_who_try_exercise'] = $totalTimesQuestionAnswered;
$data[$question_id]['lowest_score'] = round($exercise_stats['min'], 2);
$data[$question_id]['average_score'] = round($exercise_stats['average'], 2);
$data[$question_id]['highest_score'] = round($exercise_stats['max'], 2);
@ -126,7 +116,7 @@ $headers = [
get_lang('Question'),
get_lang('Answer'),
get_lang('Correct'),
get_lang('Number of learners who selected it'),
get_lang('Number of times this answer was selected'),
];
$data = [];
@ -135,7 +125,7 @@ if (!empty($question_list)) {
$id = 0;
foreach ($question_list as $question_id) {
$questionObj = Question::read($question_id);
$exercise_stats = ExerciseLib::get_student_stats_by_question(
$exercise_stats = ExerciseLib::getStudentStatsByQuestion(
$question_id,
$exerciseId,
$courseCode,
@ -144,20 +134,20 @@ if (!empty($question_list)) {
);
$answer = new Answer($question_id);
$answer_count = $answer->selectNbrAnswers();
$answerCount = $answer->selectNbrAnswers();
for ($answer_id = 1; $answer_id <= $answer_count; $answer_id++) {
$answer_info = $answer->selectAnswer($answer_id);
$is_correct = $answer->isCorrect($answer_id);
$correct_answer = 1 == $is_correct ? get_lang('Yes') : get_lang('No');
$real_answer_id = $answer->selectAutoId($answer_id);
for ($answerId = 1; $answerId <= $answerCount; $answerId++) {
$answerInfo = $answer->selectAnswer($answerId);
$isCorrect = $answer->isCorrect($answerId);
$correctAnswer = 1 == $isCorrect ? get_lang('Yes') : get_lang('No');
$realAnswerId = $answer->selectAutoId($answerId);
// Overwriting values depending of the question
// Overwriting values depending on the question
switch ($questionObj->type) {
case FILL_IN_BLANKS:
$answer_info = substr($answer_info, 0, strpos($answer_info, '::'));
$correct_answer = $is_correct;
$answers = $objExercise->fill_in_blank_answer_to_array($answer_info);
$answerInfo = substr($answerInfo, 0, strpos($answerInfo, '::'));
$correctAnswer = $isCorrect;
$answers = $objExercise->fill_in_blank_answer_to_array($answerInfo);
$counter = 0;
foreach ($answers as $answer_item) {
if (0 == $counter) {
@ -174,17 +164,9 @@ if (!empty($question_list)) {
$data[$id]['correct'] = '-';
$count = ExerciseLib::getNumberStudentsFillBlanksAnswerCount($question_id, $exerciseId);
$count = isset($count[$counter]) ? $count[$counter] : 0;
$count = $count[$counter] ?? 0;
$percentage = 0;
if (!empty($count_students)) {
$percentage = $count / $count_students * 100;
}
$data[$id]['attempts'] = Display::bar_progress(
$percentage,
false,
$count.' / '.$count_students
);
$data[$id]['attempts'] = $count;
$id++;
$counter++;
}
@ -192,96 +174,73 @@ if (!empty($question_list)) {
break;
case MATCHING:
case MATCHING_DRAGGABLE:
if (0 == $is_correct) {
if (1 == $answer_id) {
if (0 == $isCorrect) {
if (1 == $answerId) {
$data[$id]['name'] = cut($questionObj->question, 100);
} else {
$data[$id]['name'] = '-';
}
$correct = '';
for ($i = 1; $i <= $answer_count; $i++) {
$is_correct_i = $answer->isCorrect($i);
if (0 != $is_correct_i && $is_correct_i == $answer_id) {
for ($i = 1; $i <= $answerCount; $i++) {
$isCorrectI = $answer->isCorrect($i);
if (0 != $isCorrectI && $isCorrectI == $answerId) {
$correct = $answer->selectAnswer($i);
break;
}
}
$data[$id]['answer'] = $correct;
$data[$id]['correct'] = $answer_info;
$data[$id]['correct'] = $answerInfo;
$count = ExerciseLib::get_number_students_answer_count(
$answer_id,
$countOfAnswered = ExerciseLib::getCountOfAnswers(
$realAnswerId,
$question_id,
$exerciseId,
$courseCode,
$sessionId,
MATCHING
);
$percentage = 0;
if (!empty($count_students)) {
$percentage = $count / $count_students * 100;
}
$data[$id]['attempts'] = Display::bar_progress(
$percentage,
false,
$count.' / '.$count_students
);
$data[$id]['attempts'] = $countOfAnswered;
}
break;
case HOT_SPOT:
if (1 == $answer_id) {
if (1 == $answerId) {
$data[$id]['name'] = cut($questionObj->question, 100);
} else {
$data[$id]['name'] = '-';
}
$data[$id]['answer'] = $answer_info;
$data[$id]['answer'] = $answerInfo;
$data[$id]['correct'] = '-';
$count = ExerciseLib::get_number_students_answer_hotspot_count(
$answer_id,
$count = ExerciseLib::getNumberStudentsAnswerHotspotCount(
$realAnswerId,
$question_id,
$exerciseId,
$courseCode,
$sessionId
);
$percentage = 0;
if (!empty($count_students)) {
$percentage = $count / $count_students * 100;
}
$data[$id]['attempts'] = Display::bar_progress(
$percentage,
false,
$count.' / '.$count_students
);
$data[$id]['attempts'] = $count;
break;
default:
if (1 == $answer_id) {
if (1 == $answerId) {
$data[$id]['name'] = cut($questionObj->question, 100);
} else {
$data[$id]['name'] = '-';
}
$data[$id]['answer'] = $answer_info;
$data[$id]['correct'] = $correct_answer;
$data[$id]['answer'] = $answerInfo;
$data[$id]['correct'] = $correctAnswer;
$count = ExerciseLib::get_number_students_answer_count(
$real_answer_id,
$countOfAnswered = ExerciseLib::getCountOfAnswers(
$realAnswerId,
$question_id,
$exerciseId,
$courseCode,
$sessionId
);
$percentage = 0;
if (!empty($count_students)) {
$percentage = $count / $count_students * 100;
}
$data[$id]['attempts'] = Display::bar_progress(
$percentage,
false,
$count.' / '.$count_students
);
$data[$id]['attempts'] = $countOfAnswered;
}
$id++;
}

@ -3526,37 +3526,32 @@ EOT;
/**
* Get student results (only in completed exercises) stats by question.
*
* @param int $question_id
* @param int $exercise_id
* @param string $course_code
* @param int $session_id
* @param bool $onlyStudent Filter only enrolled students
*
* @return array
* @throws \Doctrine\DBAL\Exception
*/
public static function get_student_stats_by_question(
$question_id,
$exercise_id,
$course_code,
$session_id,
$onlyStudent = false
) {
$track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
$track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
public static function getStudentStatsByQuestion(
int $questionId,
int $exerciseId,
string $courseCode,
int $sessionId,
bool $onlyStudent = false
): array
{
$trackExercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
$trackAttempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
$courseUser = Database::get_main_table(TABLE_MAIN_COURSE_USER);
$question_id = (int) $question_id;
$exercise_id = (int) $exercise_id;
$course_code = Database::escape_string($course_code);
$session_id = (int) $session_id;
$courseId = api_get_course_int_id($course_code);
$questionId = (int) $questionId;
$exerciseId = (int) $exerciseId;
$courseCode = Database::escape_string($courseCode);
$sessionId = (int) $sessionId;
$courseId = api_get_course_int_id($courseCode);
$sql = "SELECT MAX(marks) as max, MIN(marks) as min, AVG(marks) as average
FROM $track_exercises e ";
$sessionCondition = api_get_session_condition($session_id, true, false, 'e.session_id');
if (true == $onlyStudent) {
FROM $trackExercises e ";
$sessionCondition = api_get_session_condition($sessionId, true, false, 'e.session_id');
if ($onlyStudent) {
$courseCondition = '';
if (empty($session_id)) {
if (empty($sessionId)) {
$courseCondition = "
INNER JOIN $courseUser c
ON (
@ -3579,14 +3574,14 @@ EOT;
$sql .= $courseCondition;
}
$sql .= "
INNER JOIN $track_attempt a
INNER JOIN $trackAttempt a
ON (
a.exe_id = e.exe_id
)
WHERE
exe_exo_id = $exercise_id AND
a.c_id = $courseId AND
question_id = $question_id AND
exe_exo_id = $exerciseId AND
e.c_id = $courseId AND
question_id = $questionId AND
e.status = ''
$sessionCondition
LIMIT 1";
@ -3739,35 +3734,28 @@ EOT;
/**
* Get number of answers to hotspot questions.
*
* @param int $answer_id
* @param int $question_id
* @param int $exercise_id
* @param string $courseId
* @param int $session_id
*
* @return int
*/
public static function get_number_students_answer_hotspot_count(
$answer_id,
$question_id,
$exercise_id,
$courseId,
$session_id
) {
$track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
$track_hotspot = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTSPOT);
public static function getNumberStudentsAnswerHotspotCount(
int $answerId,
int $questionId,
int $exerciseId,
string $courseCode,
int $sessionId
): int
{
$trackExercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
$trackHotspot = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTSPOT);
$courseUser = Database::get_main_table(TABLE_MAIN_COURSE_USER);
$courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
$courseUserSession = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
$question_id = (int) $question_id;
$answer_id = (int) $answer_id;
$exercise_id = (int) $exercise_id;
$courseId = (int) $courseId;
$session_id = (int) $session_id;
$questionId = (int) $questionId;
$answerId = (int) $answerId;
$exerciseId = (int) $exerciseId;
$courseId = api_get_course_int_id($courseCode);
$sessionId = (int) $sessionId;
if (empty($session_id)) {
if (empty($sessionId)) {
$courseCondition = "
INNER JOIN $courseUser cu
ON cu.c_id = c.id AND cu.user_id = exe_user_id";
@ -3779,25 +3767,24 @@ EOT;
$courseConditionWhere = ' AND cu.status = '.SessionEntity::STUDENT;
}
$sessionCondition = api_get_session_condition($session_id, true, false, 'e.session_id');
$sessionCondition = api_get_session_condition($sessionId, true, false, 'e.session_id');
$sql = "SELECT DISTINCT exe_user_id
FROM $track_exercises e
INNER JOIN $track_hotspot a
FROM $trackExercises e
INNER JOIN $trackHotspot a
ON (a.hotspot_exe_id = e.exe_id)
INNER JOIN $courseTable c
ON (a.c_id = c.id)
$courseCondition
WHERE
exe_exo_id = $exercise_id AND
exe_exo_id = $exerciseId AND
a.c_id = $courseId AND
hotspot_answer_id = $answer_id AND
hotspot_question_id = $question_id AND
hotspot_answer_id = $answerId AND
hotspot_question_id = $questionId AND
hotspot_correct = 1 AND
e.status = ''
$courseConditionWhere
$sessionCondition
";
$result = Database::query($sql);
$return = 0;
if ($result) {
@ -3873,7 +3860,7 @@ EOT;
a.exe_id = e.exe_id
)
INNER JOIN $courseTable c
ON c.id = a.c_id
ON c.id = e.c_id
$courseCondition
WHERE
exe_exo_id = $exercise_id AND
@ -3913,6 +3900,75 @@ EOT;
return $return;
}
/**
* Get the number of times an answer was selected.
*/
public static function getCountOfAnswers(
int $answerId,
int $questionId,
int $exerciseId,
string $courseCode,
int $sessionId,
$questionType = null,
): int
{
$trackExercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
$trackAttempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
$courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
$courseUser = Database::get_main_table(TABLE_MAIN_COURSE_USER);
$courseUserSession = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
$answerId = (int) $answerId;
$questionId = (int) $questionId;
$exerciseId = (int) $exerciseId;
$courseId = api_get_course_int_id($courseCode);
$sessionId = (int) $sessionId;
$return = 0;
$answerCondition = match ($questionType) {
FILL_IN_BLANKS => '',
default => " answer = $answerId AND ",
};
if (empty($sessionId)) {
$courseCondition = "
INNER JOIN $courseUser cu
ON cu.c_id = c.id AND cu.user_id = exe_user_id";
$courseConditionWhere = " AND relation_type <> 2 AND cu.status = ".STUDENT;
} else {
$courseCondition = "
INNER JOIN $courseUserSession cu
ON (cu.c_id = a.c_id AND cu.user_id = e.exe_user_id AND e.session_id = cu.session_id)";
$courseConditionWhere = ' AND cu.status = '.SessionEntity::STUDENT;
}
$sessionCondition = api_get_session_condition($sessionId, true, false, 'e.session_id');
$sql = "SELECT count(a.answer) as total
FROM $trackExercises e
INNER JOIN $trackAttempt a
ON (
a.exe_id = e.exe_id
)
INNER JOIN $courseTable c
ON c.id = e.c_id
$courseCondition
WHERE
exe_exo_id = $exerciseId AND
e.c_id = $courseId AND
$answerCondition
question_id = $questionId AND
e.status = ''
$courseConditionWhere
$sessionCondition
";
$result = Database::query($sql);
if ($result) {
$count = Database::fetch_array($result);
$return = (int) $count['total'];
}
return $return;
}
/**
* @param array $answer
* @param string $user_answer
@ -5444,7 +5500,7 @@ EOT;
return $trackedExercise;
}
public static function getTotalQuestionAnswered($courseId, $exerciseId, $questionId)
public static function getTotalQuestionAnswered($courseId, $exerciseId, $questionId, $onlyStudents = false): int
{
$courseId = (int) $courseId;
$exerciseId = (int) $exerciseId;
@ -5452,16 +5508,27 @@ EOT;
$attemptTable = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
$trackTable = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
$courseUser = Database::get_main_table(TABLE_MAIN_COURSE_USER);
$courseUserJoin = "";
$studentsWhere = "";
if ($onlyStudents) {
$courseUserJoin = "
INNER JOIN $courseUser cu
ON cu.c_id = te.c_id AND cu.user_id = exe_user_id";
$studentsWhere = " AND relation_type <> 2 AND cu.status = ".STUDENT;
}
$sql = "SELECT count(te.exe_id) total
$sql = "SELECT count(distinct (te.exe_id)) total
FROM $attemptTable t
INNER JOIN $trackTable te
ON (t.exe_id = te.exe_id)
$courseUserJoin
WHERE
te.c_id = $courseId AND
exe_exo_id = $exerciseId AND
t.question_id = $questionId AND
status != 'incomplete'
te.status != 'incomplete'
$studentsWhere
";
$queryTotal = Database::query($sql);
$totalRow = Database::fetch_array($queryTotal, 'ASSOC');

@ -24145,3 +24145,9 @@ msgstr "The platform owner, responsible for the processing, implements processin
msgid "Back to tests list"
msgstr "Back to tests list"
msgid "Number of times the question was answered"
msgstr "Number of times the question was answered"
msgid "Number of times this answer was selected"
msgstr "Number of times this answer was selected"

@ -24145,3 +24145,9 @@ msgstr "The platform owner, responsible for the processing, implements processin
msgid "Back to tests list"
msgstr "Back to tests list"
msgid "Number of times the question was answered"
msgstr "Number of times the question was answered"
msgid "Number of times this answer was selected"
msgstr "Number of times this answer was selected"

@ -24088,3 +24088,18 @@ msgstr "Por venir"
msgid "Past session tab"
msgstr "Finalizadas"
msgid "By checking this box, I confirm that I accept the data processing by the platform"
msgstr "Marcando esta caja, confirmo que acepto el tratamiento de datos en este plataforma"
msgid "The platform owner, responsible for the processing, implements processing of personal data to respond to your contact request. The data is mandatory. In their absence, it will not be possible to process your request."
msgstr "El propietario de la plataforma, responsable del tratamiento, implementa el tratamiento de datos personales para responde a su solicitud de contacto. Estos datos son necesarios. Sin ellos, no será posible responder a su solicitud."
msgid "Back to tests list"
msgstr "Regresar a la lista de ejercicios"
msgid "Number of times the question was answered"
msgstr "Número de veces que la pregunta fue respondida"
msgid "Number of times this answer was selected"
msgstr "Número de veces que se seleccionó esta respuesta"

Loading…
Cancel
Save