';
$html .= '
'.$title.'
';
$legendTitle = [
'Very unsure',
'Unsure',
'Declared ignorance',
'Pretty sure',
'Very sure',
];
$html .= '
';
foreach ($legendTitle as $i => $item) {
$html .= '- '.get_lang($item).'
';
}
$html .= '
';
// get the html of items
$i = 0;
$testCategory = new Testcategory();
foreach ($scoreList as $categoryId => $scoreListForCategory) {
$category = $testCategory->getCategory($categoryId);
$categoryQuestionName = '';
if ($category) {
$categoryQuestionName = $category->name;
}
if ($categoryQuestionName === '') {
$categoryName = get_lang('Without category');
} else {
$categoryName = $categoryQuestionName;
}
$html .= '
';
$html .= self::displayDegreeChartChildren(
$scoreListForCategory,
300,
$categoryName,
1,
$maxHeight,
false,
false,
$groupCategoriesByBracket
);
$html .= '
';
if ($i == 2) {
$html .= '
';
$i = 0;
} else {
$i++;
}
}
$html .= '
';
return $html.'';
$html .= '
'.$titleDisplay.'
';
$nbResponsesInc = 0;
if (isset($scoreList[4])) {
$nbResponsesInc += (int) $scoreList[4];
}
if (isset($scoreList[5])) {
$nbResponsesInc += (int) $scoreList[5];
}
$nbResponsesIng = isset($scoreList[3]) ? $scoreList[3] : 0;
$nbResponsesCor = 0;
if (isset($scoreList[1])) {
$nbResponsesCor += (int) $scoreList[1];
}
if (isset($scoreList[2])) {
$nbResponsesCor += (int) $scoreList[2];
}
$IncorrectAnswers = sprintf(get_lang('Incorrect answers: %s'), $nbResponsesInc);
$IgnoranceAnswers = sprintf(get_lang('Ignorance: %s'), $nbResponsesIng);
$CorrectAnswers = sprintf(get_lang('Correct answers: %s'), $nbResponsesCor);
$html .= '
';
$explainHistoList = null;
if ($displayExplanationText) {
// Display of histogram text
$explainHistoList = [
'Very unsure',
'Unsure',
'Declared ignorance',
'Pretty sure',
'Very sure',
];
}
foreach ($colorList as $i => $color) {
if (array_key_exists($color, $scoreList)) {
$scoreOnBottom = $scoreList[$color]; // height of the colored area on the bottom
} else {
$scoreOnBottom = 0;
}
$sizeBar = ($scoreOnBottom * $sizeRatio * 2).'px;';
if ($i == 0) {
$html .= '
';
$html .= '
';
$html .= '
'.$IncorrectAnswers.'
';
$html .= '
';
} elseif ($i == 3) {
$html .= '';
$html .= '
';
$html .= '
'.$CorrectAnswers.'
';
$html .= '
';
} elseif ($i == 2) {
$html .= '';
$html .= '
';
$html .= '
'.$IgnoranceAnswers.'
';
$html .= '
';
$html .= '
';
$html .= '
';
}
}
$html .= '
';
$html .= '
';
if ($returnHeight) {
return [$html, $verticalLineHeight];
} else {
return $html;
}
}
/**
* Return HTML code for the $scoreList of MultipleAnswerTrueFalseDegreeCertainty questions.
*
* @param $scoreList
* @param $widthTable
* @param string $title
* @param int $sizeRatio
* @param int $minHeight
* @param bool $displayExplanationText
* @param bool $returnHeight
* @param bool $groupCategoriesByBracket
* @param int $numberOfQuestions
*
* @return array|string
*/
public static function displayDegreeChartChildren(
$scoreList,
$widthTable,
$title = '',
$sizeRatio = 1,
$minHeight = 0,
$displayExplanationText = true,
$returnHeight = false,
$groupCategoriesByBracket = false,
$numberOfQuestions = 0
) {
$topAndBottomMargin = 10;
$colorList = [
self::LEVEL_DARKRED,
self::LEVEL_LIGHTRED,
self::LEVEL_WHITE,
self::LEVEL_LIGHTGREEN,
self::LEVEL_DARKGREEN,
];
// get total attempt number
$highterColorHeight = 0;
foreach ($scoreList as $color => $number) {
if ($number > $highterColorHeight) {
$highterColorHeight = $number;
}
}
$totalAttemptNumber = $numberOfQuestions;
$verticalLineHeight = $highterColorHeight * $sizeRatio * 2 + 122 + $topAndBottomMargin * 2;
if ($verticalLineHeight < $minHeight) {
$minHeightCorrection = $minHeight - $verticalLineHeight;
$verticalLineHeight += $minHeightCorrection;
}
// draw chart
$html = '';
if ($groupCategoriesByBracket) {
$title = api_preg_replace("/[^]]*$/", '', $title);
$title = ucfirst(api_preg_replace("/[\[\]]/", '', $title));
}
$textSize = 80;
$classGlobalChart = '';
if ($displayExplanationText) {
// global chart
$classGlobalChart = 'globalChart';
}
$html .= '';
$html .= ''
.$title
.' |
---|
'
;
$nbResponsesInc = 0;
if (isset($scoreList[4])) {
$nbResponsesInc += (int) $scoreList[4];
}
if (isset($scoreList[5])) {
$nbResponsesInc += (int) $scoreList[5];
}
$nbResponsesIng = isset($scoreList[3]) ? $scoreList[3] : 0;
$nbResponsesCor = 0;
if (isset($scoreList[1])) {
$nbResponsesCor += (int) $scoreList[1];
}
if (isset($scoreList[2])) {
$nbResponsesCor += (int) $scoreList[2];
}
$colWidth = $widthTable / 5;
$html .= '
'.
sprintf(get_lang('Incorrect answers: %s'), $nbResponsesInc).'
|
'.
sprintf(get_lang('Ignorance: %s'), $nbResponsesIng).'
|
'.
sprintf(get_lang('Correct answers: %s'), $nbResponsesCor).'
|
';
$html .= '';
foreach ($colorList as $i => $color) {
if (array_key_exists($color, $scoreList)) {
$scoreOnBottom = $scoreList[$color]; // height of the colored area on the bottom
} else {
$scoreOnBottom = 0;
}
$sizeOnBottom = $scoreOnBottom * $sizeRatio * 2;
if ($i == 1 || $i == 2) {
$html .= ''
;
} else {
$html .= ' | '
;
}
$html .= ' '
.$scoreOnBottom
.' '
;
$html .= ' | ';
}
$html .= '
';
if ($displayExplanationText) {
// Display of histogram text
$explainHistoList = [
'Very unsure',
'Unsure',
'Declared ignorance',
'Pretty sure',
'Very sure',
];
$html .= '';
$i = 0;
foreach ($explainHistoList as $explain) {
if ($i == 1 || $i == 2) {
$class = 'borderRight';
} else {
$class = '';
}
$html .= ''
;
$html .= get_lang($explain);
$html .= ' | ';
$i++;
}
$html .= '
';
}
$html .= '
';
if ($returnHeight) {
return [$html, $verticalLineHeight];
} else {
return $html;
}
}
/**
* return previous attempt id for this test for student, 0 if no previous attempt.
*
* @param $exeId
*
* @return int
*/
public static function getPreviousAttemptId($exeId)
{
$tblTrackEExercise = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
$exeId = (int) $exeId;
$sql = "SELECT * FROM $tblTrackEExercise
WHERE exe_id = ".$exeId;
$res = Database::query($sql);
if (empty(Database::num_rows($res))) {
// if we cannot find the exe_id
return 0;
}
$data = Database::fetch_assoc($res);
$courseCode = $data['c_id'];
$exerciseId = $data['exe_exo_id'];
$userId = $data['exe_user_id'];
$attemptDate = $data['exe_date'];
if ($attemptDate == '0000-00-00 00:00:00') {
// incomplete attempt, close it before continue
return 0;
}
// look for previous attempt
$exerciseId = (int) $exerciseId;
$userId = (int) $userId;
$sql = "SELECT *
FROM $tblTrackEExercise
WHERE c_id = '$courseCode'
AND exe_exo_id = $exerciseId
AND exe_user_id = $userId
AND status = ''
AND exe_date > '0000-00-00 00:00:00'
AND exe_date < '$attemptDate'
ORDER BY exe_date DESC";
$res = Database::query($sql);
if (Database::num_rows($res) == 0) {
// no previous attempt
return 0;
}
$data = Database::fetch_assoc($res);
return $data['exe_id'];
}
/**
* return an array of number of answer color for exe attempt
* for question type = MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY
* e.g.
* [LEVEL_DARKGREEN => 3, LEVEL_LIGHTGREEN => 0, LEVEL_WHITE => 5, LEVEL_LIGHTRED => 12, LEVEL_DARKTRED => 0].
*
* @param $exeId
*
* @return array
*/
public static function getColorNumberListForAttempt($exeId)
{
$result = [
self::LEVEL_DARKGREEN => 0,
self::LEVEL_LIGHTGREEN => 0,
self::LEVEL_WHITE => 0,
self::LEVEL_LIGHTRED => 0,
self::LEVEL_DARKRED => 0,
];
$attemptInfoList = self::getExerciseAttemptInfo($exeId);
foreach ($attemptInfoList as $attemptInfo) {
$oQuestion = new MultipleAnswerTrueFalseDegreeCertainty();
$oQuestion->read($attemptInfo['question_id']);
if ($oQuestion->type == MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY) {
$answerColor = self::getAnswerColor($exeId, $attemptInfo['question_id'], $attemptInfo['position']);
if ($answerColor) {
$result[$answerColor]++;
}
}
}
return $result;
}
/**
* return an array of number of color for question type = MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY
* for each question category.
*
* e.g.
* [
* (categoryId=)5 => [LEVEL_DARKGREEN => 3, LEVEL_WHITE => 5, LEVEL_LIGHTRED => 12]
* (categoryId=)2 => [LEVEL_DARKGREEN => 8, LEVEL_LIGHTRED => 2, LEVEL_DARKTRED => 8]
* (categoryId=)0 => [LEVEL_DARKGREEN => 1,
* LEVEL_LIGHTGREEN => 2,
* LEVEL_WHITE => 6,
* LEVEL_LIGHTRED => 1,
* LEVEL_DARKTRED => 9]
* ]
*
* @param int $exeId
*
* @return array
*/
public static function getColorNumberListForAttemptByCategory($exeId)
{
$result = [];
$attemptInfoList = self::getExerciseAttemptInfo($exeId);
foreach ($attemptInfoList as $attemptInfo) {
$oQuestion = new MultipleAnswerTrueFalseDegreeCertainty();
$oQuestion->read($attemptInfo['question_id']);
if ($oQuestion->type == MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY) {
$questionCategory = Testcategory::getCategoryForQuestion($attemptInfo['question_id']);
if (!array_key_exists($questionCategory, $result)) {
$result[$questionCategory] = [];
}
$answerColor = self::getAnswerColor($exeId, $attemptInfo['question_id'], $attemptInfo['position']);
if ($answerColor && isset($result[$questionCategory])) {
if (!isset($result[$questionCategory][$answerColor])) {
$result[$questionCategory][$answerColor] = 0;
}
$result[$questionCategory][$answerColor]++;
}
}
}
return $result;
}
/**
* Return true if answer of $exeId, $questionId, $position is correct, otherwise return false.
*
* @param $exeId
* @param $questionId
* @param $position
*
* @return int
*/
public static function getAnswerColor($exeId, $questionId, $position)
{
$attemptInfoList = self::getExerciseAttemptInfo($exeId, $questionId, $position);
if (count($attemptInfoList) != 1) {
// havent got the answer
return 0;
}
$answerCodes = $attemptInfoList[0]['answer'];
// student answer
$splitAnswer = preg_split("/:/", $answerCodes);
// get correct answer option id
$correctAnswerOptionId = self::getCorrectAnswerOptionId($splitAnswer[0]);
if ($correctAnswerOptionId == 0) {
// error returning the correct answer option id
return 0;
}
// get student answer option id
$studentAnswerOptionId = isset($splitAnswer[1]) ? $splitAnswer[1] : null;
// we got the correct answer option id, let's compare ti with the student answer
$percentage = null;
if (isset($splitAnswer[2])) {
$percentage = self::getPercentagePosition($splitAnswer[2]);
}
if ($studentAnswerOptionId == $correctAnswerOptionId) {
// yeah, student got correct answer
switch ($percentage) {
case 3:
return self::LEVEL_WHITE;
case 4:
case 5:
return self::LEVEL_LIGHTGREEN;
case 6:
case 7:
case 8:
return self::LEVEL_DARKGREEN;
default:
return 0;
}
} else {
// bummer, wrong answer dude
switch ($percentage) {
case 3:
return self::LEVEL_WHITE;
case 4:
case 5:
return self::LEVEL_LIGHTRED;
case 6:
case 7:
case 8:
return self::LEVEL_DARKRED;
default:
return 0;
}
}
}
/**
* Return the position of certitude %age choose by student.
*
* @param $optionId
*
* @return int
*/
public static function getPercentagePosition($optionId)
{
$tblAnswerOption = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION);
$courseId = api_get_course_int_id();
$optionId = (int) $optionId;
$sql = "SELECT position
FROM $tblAnswerOption
WHERE c_id = $courseId AND id = $optionId";
$res = Database::query($sql);
if (Database::num_rows($res) == 0) {
return 0;
}
$data = Database::fetch_assoc($res);
return $data['position'];
}
/**
* return the correct id from c_quiz_question_option for question idAuto.
*
* @param $idAuto
*
* @return int
*/
public static function getCorrectAnswerOptionId($idAuto)
{
$tblAnswer = Database::get_course_table(TABLE_QUIZ_ANSWER);
$courseId = api_get_course_int_id();
$idAuto = (int) $idAuto;
$sql = "SELECT correct FROM $tblAnswer
WHERE c_id = $courseId AND id_auto = $idAuto";
$res = Database::query($sql);
$data = Database::fetch_assoc($res);
if (Database::num_rows($res) > 0) {
return $data['correct'];
} else {
return 0;
}
}
/**
* return an array of exe info from track_e_attempt.
*
* @param int $exeId
* @param int $questionId
* @param int $position
*
* @return array
*/
public static function getExerciseAttemptInfo($exeId, $questionId = -1, $position = -1)
{
$result = [];
$and = '';
$questionId = (int) $questionId;
$position = (int) $position;
$exeId = (int) $exeId;
if ($questionId >= 0) {
$and .= " AND question_id = $questionId";
}
if ($position >= 0) {
$and .= " AND position = $position";
}
$tblExeAttempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
$cId = api_get_course_int_id();
$sql = "SELECT * FROM $tblExeAttempt
WHERE c_id = $cId AND exe_id = $exeId $and";
$res = Database::query($sql);
while ($data = Database::fetch_assoc($res)) {
$result[] = $data;
}
return $result;
}
/**
* @param int $exeId
*
* @return int
*/
public static function getNumberOfQuestionsForExeId($exeId)
{
$tableTrackEExercise = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
$exeId = (int) $exeId;
$sql = "SELECT exe_exo_id
FROM $tableTrackEExercise
WHERE exe_id=".$exeId;
$res = Database::query($sql);
$data = Database::fetch_assoc($res);
if ($data) {
$exerciseId = $data['exe_exo_id'];
$objectExercise = new Exercise();
$objectExercise->read($exerciseId);
return $objectExercise->getQuestionCount();
}
return 0;
}
/**
* Display student chart results for these question types.
*
* @param int $exeId
* @param Exercise $objExercice
*
* @return string
*/
public static function displayStudentsChartResults($exeId, $objExercice)
{
$numberOfQuestions = self::getNumberOfQuestionsForExeId($exeId);
$globalScoreList = self::getColorNumberListForAttempt($exeId);
$html = self::displayDegreeChart(
$globalScoreList,
600,
get_lang('Your overall results for the test'),
2,
0,
true,
false,
false,
$numberOfQuestions
);
$html .= '
';
$previousAttemptId = self::getPreviousAttemptId($exeId);
if ($previousAttemptId > 0) {
$previousAttemptScoreList = self::getColorNumberListForAttempt(
$previousAttemptId
);
$html .= self::displayDegreeChart(
$previousAttemptScoreList,
600,
get_lang('In comparison, your latest results for this test'),
2
);
$html .= '
';
}
$list = self::getColorNumberListForAttemptByCategory($exeId);
$html .= self::displayDegreeChartByCategory(
$list,
get_lang('Your results by discipline'),
1,
$objExercice
);
$html .= '
';
return $html;
}
/**
* send mail to student with degre certainty result test.
*
* @param int $userId
* @param Exercise $objExercise
* @param int $exeId
*/
public static function sendQuestionCertaintyNotification($userId, $objExercise, $exeId)
{
$userInfo = api_get_user_info($userId);
$recipientName = api_get_person_name($userInfo['firstname'],
$userInfo['lastname'],
null,
PERSON_NAME_EMAIL_ADDRESS
);
$subject = "[".get_lang('Please do not reply')."] "
.html_entity_decode(get_lang('Results for the accomplished test')." \"".$objExercise->title."\"");
// message sended to the student
$message = get_lang('Dear').' '.$recipientName.",
";
$exerciseLink = "";
$exerciseTitle = $objExercise->title;
$message .= sprintf(
get_lang('Please follow the instructions below to check your results for test %s.
'),
$exerciseTitle,
api_get_path(WEB_PATH),
$exerciseLink
);
// show histogram
$message .= self::displayStudentsChartResults($exeId, $objExercise);
$message .= get_lang('Kind regards,');
$message = api_preg_replace("/\\\n/", '', $message);
MessageManager::send_message_simple($userId, $subject, $message);
}
}