sendQuestionCertaintyNotification()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 31
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 21
nc 1
nop 3
dl 0
loc 31
rs 9.584
c 0
b 0
f 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use ChamiloSession as Session;
6
7
/**
8
 * Class MultipleAnswerTrueFalseDegreeCertainty
9
 * This class allows to instantiate an object of type MULTIPLE_ANSWER
10
 * (MULTIPLE CHOICE, MULTIPLE ANSWER), extending the class question.
11
 */
12
class MultipleAnswerTrueFalseDegreeCertainty extends Question
13
{
14
    public const LEVEL_DARKGREEN = 1;
15
    public const LEVEL_LIGHTGREEN = 2;
16
    public const LEVEL_WHITE = 3;
17
    public const LEVEL_LIGHTRED = 4;
18
    public const LEVEL_DARKRED = 5;
19
20
    public $typePicture = 'mccert.png';
21
    public $explanationLangVar = 'MultipleAnswerTrueFalseDegreeCertainty';
22
    public $optionsTitle;
23
    public $options;
24
25
    /**
26
     * Constructor.
27
     */
28
    public function __construct()
29
    {
30
        parent::__construct();
31
        $this->type = MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY;
32
        $this->isContent = $this->getIsContent();
33
        $this->optionsTitle = [1 => 'Answers', 2 => 'DegreeOfCertaintyThatMyAnswerIsCorrect'];
34
        $this->options = [
35
            1 => 'True',
36
            2 => 'False',
37
            3 => '50%',
38
            4 => '60%',
39
            5 => '70%',
40
            6 => '80%',
41
            7 => '90%',
42
            8 => '100%',
43
        ];
44
    }
45
46
    /**
47
     * Redefines Question::createAnswersForm: creates the HTML form to answer the question.
48
     *
49
     * @uses \globals $text and $class, defined in the calling script
50
     *
51
     * @param FormValidator $form
52
     *
53
     * @throws Exception
54
     * @throws HTML_QuickForm_Error
55
     */
56
    public function createAnswersForm($form)
57
    {
58
        global $text;
59
        $nbAnswers = isset($_POST['nb_answers']) ? (int) $_POST['nb_answers'] : 4;
60
        // The previous default value was 2. See task #1759.
61
        $nbAnswers += (isset($_POST['lessAnswers']) ? -1 : (isset($_POST['moreAnswers']) ? 1 : 0));
62
63
        $courseId = api_get_course_int_id();
64
        $objEx = Session::read('objExercise');
65
        $renderer = &$form->defaultRenderer();
66
        $defaults = [];
67
68
        $form->addHeader(get_lang('Answers'));
69
        $html = '<table class="table table-striped table-hover">
70
            <tr>
71
                <th width="10px">'.get_lang('Number').'</th>
72
                <th width="10px">'.get_lang('True').'</th>
73
                <th width="10px">'.get_lang('False').'</th>
74
                <th width="50%">'.get_lang('Answer').'</th>';
75
76
        // show column comment when feedback is enable
77
        if ($objEx->getFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM) {
78
            $html .= '<th width="50%">'.get_lang('Comment').'</th>';
79
        }
80
        $html .= '</tr>';
81
82
        $form->addHtml($html);
83
84
        $correct = 0;
85
        $answer = null;
86
        if (!empty($this->iid)) {
87
            $answer = new Answer($this->iid);
88
            $answer->read();
89
            if ($answer->nbrAnswers > 0 && !$form->isSubmitted()) {
90
                $nbAnswers = $answer->nbrAnswers;
91
            }
92
        }
93
94
        $form->addElement('hidden', 'nb_answers');
95
        $boxesNames = [];
96
97
        if ($nbAnswers < 1) {
98
            $nbAnswers = 1;
99
            echo Display::return_message(get_lang('YouHaveToCreateAtLeastOneAnswer'));
100
        }
101
102
        // Can be more options
103
        $optionData = Question::readQuestionOption($this->iid, $courseId);
104
105
        for ($i = 1; $i <= $nbAnswers; $i++) {
106
            $renderer->setElementTemplate(
107
                '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>',
108
                'correct['.$i.']'
109
            );
110
            $renderer->setElementTemplate(
111
                '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>',
112
                'counter['.$i.']'
113
            );
114
            $renderer->setElementTemplate(
115
                '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>',
116
                'answer['.$i.']'
117
            );
118
            $renderer->setElementTemplate(
119
                '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>',
120
                'comment['.$i.']'
121
            );
122
123
            $answerNumber = $form->addElement('text', 'counter['.$i.']', null, 'value="'.$i.'"');
124
            $answerNumber->freeze();
125
126
            $defaults['answer['.$i.']'] = '';
127
            $defaults['comment['.$i.']'] = '';
128
            $defaults['correct['.$i.']'] = '';
129
130
            if (is_object($answer)) {
131
                $defaults['answer['.$i.']'] = isset($answer->answer[$i]) ? $answer->answer[$i] : '';
132
                $defaults['comment['.$i.']'] = isset($answer->comment[$i]) ? $answer->comment[$i] : '';
133
                $defaults['weighting['.$i.']'] = isset($answer->weighting[$i]) ? float_format($answer->weighting[$i], 1) : '';
134
                $correct = isset($answer->correct[$i]) ? $answer->correct[$i] : '';
135
                $defaults['correct['.$i.']'] = $correct;
136
137
                $j = 1;
138
                if (!empty($optionData)) {
139
                    foreach ($optionData as $id => $data) {
140
                        $rdoCorrect = $form->addElement('radio', 'correct['.$i.']', null, null, $id);
141
142
                        if (isset($_POST['correct']) && isset($_POST['correct'][$i]) && $id == $_POST['correct'][$i]) {
143
                            $rdoCorrect->setValue(Security::remove_XSS($_POST['correct'][$i]));
144
                        }
145
146
                        $j++;
147
                        if ($j == 3) {
148
                            break;
149
                        }
150
                    }
151
                }
152
            } else {
153
                $form->addElement('radio', 'correct['.$i.']', null, null, 1);
154
                $form->addElement('radio', 'correct['.$i.']', null, null, 2);
155
            }
156
157
            $boxesNames[] = 'correct['.$i.']';
158
            $txtAnswer = $form->addElement(
159
                'html_editor',
160
                'answer['.$i.']',
161
                null,
162
                ['style' => 'vertical-align:middle;'],
163
                ['ToolbarSet' => 'TestProposedAnswer', 'Width' => '100%', 'Height' => '100']
164
            );
165
            $form->addRule('answer['.$i.']', get_lang('ThisFieldIsRequired'), 'required');
166
            $form->applyFilter("answer[$i]", 'attr_on_filter');
167
168
            if (isset($_POST['answer']) && isset($_POST['answer'][$i])) {
169
                $txtAnswer->setValue(Security::remove_XSS($_POST['answer'][$i]));
170
            }
171
172
            // show comment when feedback is enable
173
            if ($objEx->getFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM) {
174
                $txtComment = $form->addElement(
175
                    'html_editor',
176
                    'comment['.$i.']',
177
                    null,
178
                    ['style' => 'vertical-align:middle;'],
179
                    ['ToolbarSet' => 'TestProposedAnswer', 'Width' => '100%', 'Height' => '100']
180
                );
181
                $form->applyFilter("comment[$i]", 'attr_on_filter');
182
183
                if (isset($_POST['comment']) && isset($_POST['comment'][$i])) {
184
                    $txtComment->setValue(Security::remove_XSS($_POST['comment'][$i]));
185
                }
186
            }
187
            $form->addElement('html', '</tr>');
188
        }
189
190
        $form->addElement('html', '</table>');
191
        $form->addElement('html', '<br />');
192
193
        // 3 scores
194
        $txtOption1 = $form->addElement('text', 'option[1]', get_lang('Correct'), ['value' => '1']);
195
        $txtOption2 = $form->addElement('text', 'option[2]', get_lang('Wrong'), ['value' => '-0.5']);
196
197
        $form->addElement('hidden', 'option[3]', 0);
198
199
        $form->addRule('option[1]', get_lang('ThisFieldIsRequired'), 'required');
200
        $form->addRule('option[2]', get_lang('ThisFieldIsRequired'), 'required');
201
202
        $form->addElement('html', '</tr><table>');
203
        $form->addElement('hidden', 'options_count', 3);
204
        $form->addElement('html', '</table><br /><br />');
205
206
        //Extra values True, false, Don't known
207
        if (!empty($this->extra)) {
208
            $scores = explode(':', $this->extra);
209
            if (!empty($scores)) {
210
                $txtOption1->setValue($scores[0]);
211
                $txtOption2->setValue($scores[1]);
212
            }
213
        }
214
215
        if ($objEx->edit_exercise_in_lp === true ||
216
            (empty($this->exerciseList) && empty($objEx->iid))
217
        ) {
218
            $form->addElement('submit', 'lessAnswers', get_lang('LessAnswer'), 'class="btn btn-danger minus"');
219
            $form->addElement('submit', 'moreAnswers', get_lang('PlusAnswer'), 'class="btn btn-primary plus"');
220
            $form->addElement('submit', 'submitQuestion', $text, 'class = "btn btn-primary"');
221
        }
222
        $renderer->setElementTemplate('{element}&nbsp;', 'lessAnswers');
223
        $renderer->setElementTemplate('{element}&nbsp;', 'submitQuestion');
224
        $renderer->setElementTemplate('{element}&nbsp;', 'moreAnswers');
225
        $form->addElement('html', '</div></div>');
226
227
        if (!empty($this->iid) && !$form->isSubmitted()) {
228
            $form->setDefaults($defaults);
229
        }
230
231
        $form->setConstants(['nb_answers' => $nbAnswers]);
232
    }
233
234
    /**
235
     * abstract function which creates the form to create / edit the answers of the question.
236
     *
237
     * @param FormValidator $form
238
     * @param Exercise      $exercise
239
     */
240
    public function processAnswersCreation($form, $exercise)
241
    {
242
        $questionWeighting = 0;
243
        $objAnswer = new Answer($this->iid);
244
        $nbAnswers = $form->getSubmitValue('nb_answers');
245
        $courseId = api_get_course_int_id();
246
        $correct = [];
247
        $options = Question::readQuestionOption($this->iid, $courseId);
248
249
        if (!empty($options)) {
250
            foreach ($options as $optionData) {
251
                $id = $optionData['iid'];
252
                unset($optionData['iid']);
253
                Question::updateQuestionOption($id, $optionData, $courseId);
254
            }
255
        } else {
256
            for ($i = 1; $i <= 8; $i++) {
257
                $lastId = Question::saveQuestionOption($this->iid, $this->options[$i], $courseId, $i);
258
                $correct[$i] = $lastId;
259
            }
260
        }
261
262
        /* Getting quiz_question_options (true, false, doubt) because
263
          it's possible that there are more options in the future */
264
        $newOptions = Question::readQuestionOption($this->iid, $courseId);
265
        $sortedByPosition = [];
266
        foreach ($newOptions as $item) {
267
            $sortedByPosition[$item['position']] = $item;
268
        }
269
270
        /* Saving quiz_question.extra values that has the correct scores of
271
          the true, false, doubt options registered in this format
272
          XX:YY:ZZZ where XX is a float score value. */
273
        $extraValues = [];
274
        for ($i = 1; $i <= 3; $i++) {
275
            $score = trim($form->getSubmitValue('option['.$i.']'));
276
            $extraValues[] = $score;
277
        }
278
        $this->setExtra(implode(':', $extraValues));
279
280
        for ($i = 1; $i <= $nbAnswers; $i++) {
281
            $answer = trim($form->getSubmitValue('answer['.$i.']'));
282
            $comment = trim($form->getSubmitValue('comment['.$i.']'));
283
            $goodAnswer = trim($form->getSubmitValue('correct['.$i.']'));
284
            if (empty($options)) {
285
                // If this is the first time that the question is created then change
286
                // the default values from the form 1 and 2 by the correct "option id" registered
287
                $goodAnswer = $sortedByPosition[$goodAnswer]['iid'];
288
            }
289
            $questionWeighting += $extraValues[0]; //By default 0 has the correct answers
290
            $objAnswer->createAnswer($answer, $goodAnswer, $comment, '', $i);
291
        }
292
293
        // saves the answers into the data base
294
        $objAnswer->save();
295
296
        // sets the total weighting of the question
297
        $this->updateWeighting($questionWeighting);
298
        $this->save($exercise);
299
    }
300
301
    /**
302
     * {@inheritdoc}
303
     */
304
    public function return_header(Exercise $exercise, $counter = null, $score = [])
305
    {
306
        $header = parent::return_header($exercise, $counter, $score);
307
        $header .= '<table class="'.$this->question_table_class.'"><tr>';
308
        $header .= '<th>'.get_lang('Choice').'</th>';
309
310
        if ($exercise->showExpectedChoiceColumn()) {
311
            $header .= '<th>'.get_lang('ExpectedChoice').'</th>';
312
        }
313
314
        $header .= '<th>'
315
            .get_lang('Answer')
316
            .'</th><th colspan="2" style="text-align:center;">'
317
            .get_lang('YourDegreeOfCertainty')
318
            .'</th>'
319
        ;
320
321
        if (false === $exercise->hideComment) {
322
            if ($exercise->getFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM) {
323
                $header .= '<th>'.get_lang('Comment').'</th>';
324
            }
325
        }
326
        $header .= '</tr>';
327
328
        return $header;
329
    }
330
331
    /**
332
     * Get color code, status, label and description for the current answer.
333
     *
334
     * @param string $studentAnswer
335
     * @param string $expectedAnswer
336
     * @param int    $studentDegreeChoicePosition
337
     *
338
     * @return array An array with indexes 'color', 'background-color', 'status', 'label' and 'description'
339
     */
340
    public function getResponseDegreeInfo($studentAnswer, $expectedAnswer, $studentDegreeChoicePosition)
341
    {
342
        $result = [];
343
        if ($studentDegreeChoicePosition == 3) {
344
            $result = [
345
                'color' => '#000000',
346
                'background-color' => '#F6BA2A',
347
                'status' => self::LEVEL_WHITE,
348
                'label' => get_lang('DegreeOfCertaintyDeclaredIgnorance'),
349
                'description' => get_lang('DegreeOfCertaintyDeclaredIgnoranceDescription'),
350
            ];
351
        } else {
352
            $checkResult = $studentAnswer == $expectedAnswer ? true : false;
353
            if ($checkResult) {
354
                if ($studentDegreeChoicePosition >= 6) {
355
                    $result = [
356
                        'color' => '#FFFFFF',
357
                        'background-color' => '#1E9C55',
358
                        'status' => self::LEVEL_DARKGREEN,
359
                        'label' => get_lang('DegreeOfCertaintyVerySure'),
360
                        'description' => get_lang('DegreeOfCertaintyVerySureDescription'),
361
                    ];
362
                } elseif ($studentDegreeChoicePosition >= 4 && $studentDegreeChoicePosition <= 5) {
363
                    $result = [
364
                        'color' => '#000000',
365
                        'background-color' => '#B1E183',
366
                        'status' => self::LEVEL_LIGHTGREEN,
367
                        'label' => get_lang('DegreeOfCertaintyPrettySure'),
368
                        'description' => get_lang('DegreeOfCertaintyPrettySureDescription'),
369
                    ];
370
                }
371
            } else {
372
                if ($studentDegreeChoicePosition >= 6) {
373
                    $result = [
374
                        'color' => '#FFFFFF',
375
                        'background-color' => '#ED4040',
376
                        'status' => self::LEVEL_DARKRED,
377
                        'label' => get_lang('DegreeOfCertaintyVeryUnsure'),
378
                        'description' => get_lang('DegreeOfCertaintyVeryUnsureDescription'),
379
                    ];
380
                } elseif ($studentDegreeChoicePosition >= 4 && $studentDegreeChoicePosition <= 5) {
381
                    $result = [
382
                        'color' => '#000000',
383
                        'background-color' => '#F79B88',
384
                        'status' => self::LEVEL_LIGHTRED,
385
                        'label' => get_lang('DegreeOfCertaintyUnsure'),
386
                        'description' => get_lang('DegreeOfCertaintyUnsureDescription'),
387
                    ];
388
                }
389
            }
390
        }
391
392
        return $result;
393
    }
394
395
    /**
396
     * Method to show the code color and his meaning for the test result.
397
     */
398
    public static function showColorCodes()
399
    {
400
        ?>
401
        <table class="fc-border-separate" cellspacing="0" style="width:600px;
402
            margin: auto; border: 3px solid #A39E9E;" >
403
            <tr style="border-bottom: 1px solid #A39E9E;">
404
                <td style="width:15%; height:30px; background-color: #088A08; border-right: 1px solid #A39E9E;">
405
                    &nbsp;
406
                </td>
407
                <td style="padding-left:10px;">
408
                    <b><?php echo get_lang('DegreeOfCertaintyVerySure'); ?> :</b>
409
                    <?php echo get_lang('DegreeOfCertaintyVerySureDescription'); ?>
410
                </td>
411
            </tr>
412
            <tr style="border-bottom: 1px solid #A39E9E;">
413
                <td style="width:15%; height:30px; background-color: #A9F5A9; border-right: 1px solid #A39E9E;">
414
                    &nbsp;
415
                </td>
416
                <td style="padding-left:10px;">
417
                    <b><?php echo get_lang('DegreeOfCertaintyPrettySure'); ?> :</b>
418
                    <?php echo get_lang('DegreeOfCertaintyPrettySureDescription'); ?>
419
                </td>
420
            </tr>
421
            <tr style="border: 1px solid #A39E9E;">
422
                <td style="width:15%; height:30px; background-color: #FFFFFF; border-right: 1px solid #A39E9E;">
423
                    &nbsp;
424
                </td>
425
                <td style="padding-left:10px;">
426
                    <b><?php echo get_lang('DegreeOfCertaintyDeclaredIgnorance'); ?> :</b>
427
                    <?php echo get_lang('DegreeOfCertaintyDeclaredIgnoranceDescription'); ?>
428
                </td>
429
            </tr>
430
            <tr style="border: 1px solid #A39E9E;">
431
                <td style="width:15%; height:30px; background-color: #F6CECE; border-right: 1px solid #A39E9E;">
432
                    &nbsp;
433
                </td>
434
                <td style="padding-left:10px;">
435
                    <b><?php echo get_lang('DegreeOfCertaintyUnsure'); ?> :</b>
436
                    <?php echo get_lang('DegreeOfCertaintyUnsureDescription'); ?>
437
                </td>
438
            </tr>
439
            <tr style="border-bottom: 1px solid #A39E9E;">
440
                <td style="width:15%; height:30px; background-color: #FE2E2E; border-right: 1px solid #A39E9E;">
441
                    &nbsp;
442
                </td>
443
                <td style="padding-left:10px;">
444
                    <b><?php echo get_lang('DegreeOfCertaintyVeryUnsure'); ?> :</b>
445
                    <?php echo get_lang('DegreeOfCertaintyVeryUnsureDescription'); ?>
446
                </td>
447
            </tr>
448
        </table><br/>
449
        <?php
450
    }
451
452
    /**
453
     * Display basic bar charts of results by category of questions.
454
     *
455
     * @param array  $scoreListAll
456
     * @param string $title        The block title
457
     * @param int    $sizeRatio
458
     *
459
     * @return string The HTML/CSS code for the charts block
460
     */
461
    public static function displayDegreeChartByCategory($scoreListAll, $title, $sizeRatio = 1)
462
    {
463
        $maxHeight = 0;
464
        $groupCategoriesByBracket = false;
465
        if ($groupCategoriesByBracket) {
466
            $scoreList = [];
467
            $categoryPrefixList = [];
468
            // categoryPrefix['Math'] = firstCategoryId for this prefix
469
            // rebuild $scoreList factorizing data with category prefix
470
            foreach ($scoreListAll as $categoryId => $scoreListForCategory) {
471
                $objCategory = new Testcategory();
472
                $objCategoryNum = $objCategory->getCategory($categoryId);
473
                preg_match("/^\[([^]]+)\]/", $objCategoryNum->name, $matches);
474
475
                if (count($matches) > 1) {
476
                    // check if we have already see this prefix
477
                    if (array_key_exists($matches[1], $categoryPrefixList)) {
478
                        // add the result color for this entry
479
                        $scoreList[$categoryPrefixList[$matches[1]]][self::LEVEL_DARKGREEN] +=
480
                            $scoreListForCategory[self::LEVEL_DARKGREEN];
481
                        $scoreList[$categoryPrefixList[$matches[1]]][self::LEVEL_LIGHTGREEN] +=
482
                            $scoreListForCategory[self::LEVEL_LIGHTGREEN];
483
                        $scoreList[$categoryPrefixList[$matches[1]]][self::LEVEL_WHITE] +=
484
                            $scoreListForCategory[self::LEVEL_WHITE];
485
                        $scoreList[$categoryPrefixList[$matches[1]]][self::LEVEL_LIGHTRED] +=
486
                            $scoreListForCategory[self::LEVEL_LIGHTRED];
487
                        $scoreList[$categoryPrefixList[$matches[1]]][self::LEVEL_DARKRED] +=
488
                            $scoreListForCategory[self::LEVEL_DARKRED];
489
                    } else {
490
                        $categoryPrefixList[$matches[1]] = $categoryId;
491
                        $scoreList[$categoryId] = $scoreListAll[$categoryId];
492
                    }
493
                } else {
494
                    // doesn't match the prefix '[math] Math category'
495
                    $scoreList[$categoryId] = $scoreListAll[$categoryId];
496
                }
497
            }
498
        } else {
499
            $scoreList = $scoreListAll;
500
        }
501
502
        // get the max height of item to have each table the same height if displayed side by side
503
        $testCategory = new TestCategory();
504
        foreach ($scoreList as $categoryId => $scoreListForCategory) {
505
            $category = $testCategory->getCategory($categoryId);
506
            if ($category) {
507
                $categoryQuestionName = $category->name;
508
            }
509
            list($noValue, $height) = self::displayDegreeChartChildren(
510
                $scoreListForCategory,
511
                300,
512
                '',
513
                1,
514
                0,
515
                false,
516
                true,
517
                0
518
            );
519
            if ($height > $maxHeight) {
520
                $maxHeight = $height;
521
            }
522
        }
523
524
        if (count($scoreList) > 1) {
525
            $boxWidth = $sizeRatio * 300 * 2 + 54;
526
        } else {
527
            $boxWidth = $sizeRatio * 300 + 54;
528
        }
529
530
        $html = '<div class="row-chart">';
531
        $html .= '<h4 class="chart-title">'.$title.'</h4>';
532
533
        $legendTitle = [
534
            'DegreeOfCertaintyVeryUnsure',
535
            'DegreeOfCertaintyUnsure',
536
            'DegreeOfCertaintyDeclaredIgnorance',
537
            'DegreeOfCertaintyPrettySure',
538
            'DegreeOfCertaintyVerySure',
539
        ];
540
        $html .= '<ul class="chart-legend">';
541
        foreach ($legendTitle as $i => $item) {
542
            $html .= '<li><i class="fa fa-square square_color'.$i.'" aria-hidden="true"></i> '.get_lang($item).'</li>';
543
        }
544
        $html .= '</ul>';
545
546
        // get the html of items
547
        $i = 0;
548
        $testCategory = new Testcategory();
549
        foreach ($scoreList as $categoryId => $scoreListForCategory) {
550
            $category = $testCategory->getCategory($categoryId);
551
            $categoryQuestionName = '';
552
            if ($category) {
553
                $categoryQuestionName = $category->name;
554
            }
555
556
            if ($categoryQuestionName === '') {
557
                $categoryName = get_lang('WithoutCategory');
558
            } else {
559
                $categoryName = $categoryQuestionName;
560
            }
561
562
            $html .= '<div class="col-md-4">';
563
            $html .= self::displayDegreeChartChildren(
564
                $scoreListForCategory,
565
                300,
566
                $categoryName,
567
                1,
568
                $maxHeight,
569
                false,
570
                false,
571
                $groupCategoriesByBracket
572
            );
573
            $html .= '</div>';
574
575
            if ($i == 2) {
576
                $html .= '<div style="clear:both; height: 10px;">&nbsp;</div>';
577
                $i = 0;
578
            } else {
579
                $i++;
580
            }
581
        }
582
        $html .= '</div>';
583
584
        return $html.'<div style="clear:both; height: 10px;" >&nbsp;</div>';
585
    }
586
587
    /**
588
     * Return HTML code for the $scoreList of MultipleAnswerTrueFalseDegreeCertainty questions.
589
     *
590
     * @param        $scoreList
591
     * @param        $widthTable
592
     * @param string $title
593
     * @param int    $sizeRatio
594
     * @param int    $minHeight
595
     * @param bool   $displayExplanationText
596
     * @param bool   $returnHeight
597
     * @param bool   $groupCategoriesByBracket
598
     * @param int    $numberOfQuestions
599
     *
600
     * @return array|string
601
     */
602
    public static function displayDegreeChart(
603
        $scoreList,
604
        $widthTable,
605
        $title = '',
606
        $sizeRatio = 1,
607
        $minHeight = 0,
608
        $displayExplanationText = true,
609
        $returnHeight = false,
610
        $groupCategoriesByBracket = false,
611
        $numberOfQuestions = 0
612
    ) {
613
        $topAndBottomMargin = 10;
614
        $colorList = [
615
            self::LEVEL_DARKRED,
616
            self::LEVEL_LIGHTRED,
617
            self::LEVEL_WHITE,
618
            self::LEVEL_LIGHTGREEN,
619
            self::LEVEL_DARKGREEN,
620
        ];
621
622
        // get total attempt number
623
        $highterColorHeight = 0;
624
        foreach ($scoreList as $color => $number) {
625
            if ($number > $highterColorHeight) {
626
                $highterColorHeight = $number;
627
            }
628
        }
629
630
        $totalAttemptNumber = $numberOfQuestions;
631
        $verticalLineHeight = $highterColorHeight * $sizeRatio * 2 + 122 + $topAndBottomMargin * 2;
632
        if ($verticalLineHeight < $minHeight) {
633
            $minHeightCorrection = $minHeight - $verticalLineHeight;
634
            $verticalLineHeight += $minHeightCorrection;
635
        }
636
637
        // draw chart
638
        $html = '';
639
640
        if ($groupCategoriesByBracket) {
641
            $title = api_preg_replace("/[^]]*$/", '', $title);
642
            $title = ucfirst(api_preg_replace("/[\[\]]/", '', $title));
643
        }
644
645
        $titleDisplay = (strpos($title, "ensemble") > 0) ?
646
            $title."<br/>($totalAttemptNumber questions)" :
647
            $title;
648
        $textSize = (
649
            strpos($title, 'ensemble') > 0 ||
650
            strpos($title, 'votre dernier résultat à ce test') > 0
651
        ) ? 100 : 80;
652
653
        $html .= '<div class="row-chart">';
654
        $html .= '<h4 class="chart-title">'.$titleDisplay.'</h4>';
655
656
        $nbResponsesInc = 0;
657
        if (isset($scoreList[4])) {
658
            $nbResponsesInc += (int) $scoreList[4];
659
        }
660
        if (isset($scoreList[5])) {
661
            $nbResponsesInc += (int) $scoreList[5];
662
        }
663
664
        $nbResponsesIng = isset($scoreList[3]) ? $scoreList[3] : 0;
665
666
        $nbResponsesCor = 0;
667
        if (isset($scoreList[1])) {
668
            $nbResponsesCor += (int) $scoreList[1];
669
        }
670
        if (isset($scoreList[2])) {
671
            $nbResponsesCor += (int) $scoreList[2];
672
        }
673
674
        $IncorrectAnswers = sprintf(get_lang('IncorrectAnswersX'), $nbResponsesInc);
675
        $IgnoranceAnswers = sprintf(get_lang('IgnoranceAnswersX'), $nbResponsesIng);
676
        $CorrectAnswers = sprintf(get_lang('CorrectAnswersX'), $nbResponsesCor);
677
678
        $html .= '<div class="chart-grid">';
679
680
        $explainHistoList = null;
681
        if ($displayExplanationText) {
682
            // Display of histogram text
683
            $explainHistoList = [
684
                'DegreeOfCertaintyVeryUnsure',
685
                'DegreeOfCertaintyUnsure',
686
                'DegreeOfCertaintyDeclaredIgnorance',
687
                'DegreeOfCertaintyPrettySure',
688
                'DegreeOfCertaintyVerySure',
689
            ];
690
        }
691
692
        foreach ($colorList as $i => $color) {
693
            if (array_key_exists($color, $scoreList)) {
694
                $scoreOnBottom = $scoreList[$color]; // height of the colored area on the bottom
695
            } else {
696
                $scoreOnBottom = 0;
697
            }
698
            $sizeBar = ($scoreOnBottom * $sizeRatio * 2).'px;';
699
700
            if ($i == 0) {
701
                $html .= '<div class="item">';
702
                $html .= '<div class="panel-certaint" style="min-height:'.$verticalLineHeight.'px; position: relative;">';
703
                $html .= '<div class="answers-title">'.$IncorrectAnswers.'</div>';
704
                $html .= '<ul class="certaint-list-two">';
705
            } elseif ($i == 3) {
706
                $html .= '<div class="item">';
707
                $html .= '<div class="panel-certaint" style="height:'.$verticalLineHeight.'px;  position: relative;">';
708
                $html .= '<div class="answers-title">'.$CorrectAnswers.'</div>';
709
                $html .= '<ul class="certaint-list-two">';
710
            } elseif ($i == 2) {
711
                $html .= '<div class="item">';
712
                $html .= '<div class="panel-certaint" style="height:'.$verticalLineHeight.'px;  position: relative;">';
713
                $html .= '<div class="answers-title">'.$IgnoranceAnswers.'</div>';
714
                $html .= '<ul class="certaint-list">';
715
            }
716
            $html .= '<li>';
717
            $html .= '<div class="certaint-score">';
718
            $html .= $scoreOnBottom;
719
            $html .= '</div>';
720
            $html .= '<div class="levelbar_'.$color.'" style="height:'.$sizeBar.'">&nbsp;</div>';
721
            $html .= '<div class="certaint-text">'.get_lang($explainHistoList[$i]).'</div>';
722
            $html .= '</li>';
723
724
            if ($i == 1 || $i == 2 || $i == 4) {
725
                $html .= '</ul>';
726
                $html .= '</div>';
727
                $html .= '</div>';
728
            }
729
        }
730
731
        $html .= '</div>';
732
        $html .= '</div>';
733
734
        if ($returnHeight) {
735
            return [$html, $verticalLineHeight];
736
        } else {
737
            return $html;
738
        }
739
    }
740
741
    /**
742
     * Return HTML code for the $scoreList of MultipleAnswerTrueFalseDegreeCertainty questions.
743
     *
744
     * @param        $scoreList
745
     * @param        $widthTable
746
     * @param string $title
747
     * @param int    $sizeRatio
748
     * @param int    $minHeight
749
     * @param bool   $displayExplanationText
750
     * @param bool   $returnHeight
751
     * @param bool   $groupCategoriesByBracket
752
     * @param int    $numberOfQuestions
753
     *
754
     * @return array|string
755
     */
756
    public static function displayDegreeChartChildren(
757
        $scoreList,
758
        $widthTable,
759
        $title = '',
760
        $sizeRatio = 1,
761
        $minHeight = 0,
762
        $displayExplanationText = true,
763
        $returnHeight = false,
764
        $groupCategoriesByBracket = false,
765
        $numberOfQuestions = 0
766
    ) {
767
        $topAndBottomMargin = 10;
768
        $colorList = [
769
            self::LEVEL_DARKRED,
770
            self::LEVEL_LIGHTRED,
771
            self::LEVEL_WHITE,
772
            self::LEVEL_LIGHTGREEN,
773
            self::LEVEL_DARKGREEN,
774
        ];
775
776
        // get total attempt number
777
        $highterColorHeight = 0;
778
        foreach ($scoreList as $color => $number) {
779
            if ($number > $highterColorHeight) {
780
                $highterColorHeight = $number;
781
            }
782
        }
783
784
        $totalAttemptNumber = $numberOfQuestions;
785
        $verticalLineHeight = $highterColorHeight * $sizeRatio * 2 + 122 + $topAndBottomMargin * 2;
786
        if ($verticalLineHeight < $minHeight) {
787
            $minHeightCorrection = $minHeight - $verticalLineHeight;
788
            $verticalLineHeight += $minHeightCorrection;
789
        }
790
791
        // draw chart
792
        $html = '';
793
794
        if ($groupCategoriesByBracket) {
795
            $title = api_preg_replace("/[^]]*$/", '', $title);
796
            $title = ucfirst(api_preg_replace("/[\[\]]/", '', $title));
797
        }
798
799
        $textSize = 80;
800
801
        $classGlobalChart = '';
802
        if ($displayExplanationText) {
803
            // global chart
804
            $classGlobalChart = 'globalChart';
805
        }
806
807
        $html .= '<table class="certaintyTable" style="height :'.$verticalLineHeight.'px; margin-bottom: 10px;" >';
808
        $html .= '<tr><th colspan="5" class="'.$classGlobalChart.'">'
809
            .$title
810
            .'</th><tr>'
811
        ;
812
813
        $nbResponsesInc = 0;
814
        if (isset($scoreList[4])) {
815
            $nbResponsesInc += (int) $scoreList[4];
816
        }
817
        if (isset($scoreList[5])) {
818
            $nbResponsesInc += (int) $scoreList[5];
819
        }
820
821
        $nbResponsesIng = isset($scoreList[3]) ? $scoreList[3] : 0;
822
823
        $nbResponsesCor = 0;
824
        if (isset($scoreList[1])) {
825
            $nbResponsesCor += (int) $scoreList[1];
826
        }
827
        if (isset($scoreList[2])) {
828
            $nbResponsesCor += (int) $scoreList[2];
829
        }
830
831
        $colWidth = $widthTable / 5;
832
833
        $html .= '<tr>
834
                <td class="firstLine borderRight '.$classGlobalChart.'"
835
                    colspan="2"
836
                    style="width:'.($colWidth * 2).'px; line-height: 15px; font-size:'.$textSize.'%;">'.
837
            sprintf(get_lang('IncorrectAnswersX'), $nbResponsesInc).'
838
                </td>
839
                <td class="firstLine borderRight '.$classGlobalChart.'"
840
                    style="width:'.$colWidth.'px; line-height: 15px; font-size :'.$textSize.'%;">'.
841
            sprintf(get_lang('IgnoranceAnswersX'), $nbResponsesIng).'
842
                </td>
843
                <td class="firstLine '.$classGlobalChart.'"
844
                    colspan="2"
845
                    style="width:'.($colWidth * 2).'px; line-height: 15px; font-size:'.$textSize.'%;">'.
846
            sprintf(get_lang('CorrectAnswersX'), $nbResponsesCor).'
847
                </td>
848
            </tr>';
849
        $html .= '<tr>';
850
851
        foreach ($colorList as $i => $color) {
852
            if (array_key_exists($color, $scoreList)) {
853
                $scoreOnBottom = $scoreList[$color]; // height of the colored area on the bottom
854
            } else {
855
                $scoreOnBottom = 0;
856
            }
857
            $sizeOnBottom = $scoreOnBottom * $sizeRatio * 2;
858
            if ($i == 1 || $i == 2) {
859
                $html .= '<td width="'
860
                    .$colWidth
861
                    .'px" style="border-right: 1px dotted #7FC5FF; vertical-align: bottom;font-size: '
862
                    .$textSize
863
                    .'%;">'
864
                ;
865
            } else {
866
                $html .= '<td width="'
867
                    .$colWidth
868
                    .'px" style="vertical-align: bottom;font-size: '
869
                    .$textSize
870
                    .'%;">'
871
                ;
872
            }
873
            $html .= '<div class="certaint-score">'
874
                .$scoreOnBottom
875
                .'</div><div class="levelbar_'
876
                .$color
877
                .'" style="height: '
878
                .$sizeOnBottom
879
                .'px;">&nbsp;</div>'
880
            ;
881
            $html .= '</td>';
882
        }
883
884
        $html .= '</tr>';
885
886
        if ($displayExplanationText) {
887
            // Display of histogram text
888
            $explainHistoList = [
889
                'DegreeOfCertaintyVeryUnsure',
890
                'DegreeOfCertaintyUnsure',
891
                'DegreeOfCertaintyDeclaredIgnorance',
892
                'DegreeOfCertaintyPrettySure',
893
                'DegreeOfCertaintyVerySure',
894
            ];
895
            $html .= '<tr>';
896
            $i = 0;
897
            foreach ($explainHistoList as $explain) {
898
                if ($i == 1 || $i == 2) {
899
                    $class = 'borderRight';
900
                } else {
901
                    $class = '';
902
                }
903
                $html .= '<td class="firstLine '
904
                    .$class
905
                    .' '
906
                    .$classGlobalChart
907
                    .'" style="width="'
908
                    .$colWidth
909
                    .'px; font-size:'
910
                    .$textSize
911
                    .'%;">'
912
                ;
913
                $html .= get_lang($explain);
914
                $html .= '</td>';
915
                $i++;
916
            }
917
            $html .= '</tr>';
918
        }
919
        $html .= '</table></center>';
920
921
        if ($returnHeight) {
922
            return [$html, $verticalLineHeight];
923
        } else {
924
            return $html;
925
        }
926
    }
927
928
    /**
929
     * return previous attempt id for this test for student, 0 if no previous attempt.
930
     *
931
     * @param $exeId
932
     *
933
     * @return int
934
     */
935
    public static function getPreviousAttemptId($exeId)
936
    {
937
        $tblTrackEExercise = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
938
        $exeId = (int) $exeId;
939
        $sql = "SELECT * FROM $tblTrackEExercise
940
                WHERE exe_id = ".$exeId;
941
        $res = Database::query($sql);
942
943
        if (empty(Database::num_rows($res))) {
944
            // if we cannot find the exe_id
945
            return 0;
946
        }
947
948
        $data = Database::fetch_assoc($res);
949
        $courseCode = $data['c_id'];
950
        $exerciseId = $data['exe_exo_id'];
951
        $userId = $data['exe_user_id'];
952
        $attemptDate = $data['exe_date'];
953
954
        if ($attemptDate == '0000-00-00 00:00:00') {
955
            // incomplete attempt, close it before continue
956
            return 0;
957
        }
958
959
        // look for previous attempt
960
        $exerciseId = (int) $exerciseId;
961
        $userId = (int) $userId;
962
        $sql = "SELECT *
963
            FROM $tblTrackEExercise
964
            WHERE c_id = '$courseCode'
965
            AND exe_exo_id = $exerciseId
966
            AND exe_user_id = $userId
967
            AND status = ''
968
            AND exe_date > '0000-00-00 00:00:00'
969
            AND exe_date < '$attemptDate'
970
            ORDER BY exe_date DESC";
971
972
        $res = Database::query($sql);
973
974
        if (Database::num_rows($res) == 0) {
975
            // no previous attempt
976
            return 0;
977
        }
978
979
        $data = Database::fetch_assoc($res);
980
981
        return $data['exe_id'];
982
    }
983
984
    /**
985
     * return an array of number of answer color for exe attempt
986
     * for question type = MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY
987
     * e.g.
988
     * [LEVEL_DARKGREEN => 3, LEVEL_LIGHTGREEN => 0, LEVEL_WHITE => 5, LEVEL_LIGHTRED => 12, LEVEL_DARKTRED => 0].
989
     *
990
     * @param $exeId
991
     *
992
     * @return array
993
     */
994
    public static function getColorNumberListForAttempt($exeId)
995
    {
996
        $result = [
997
            self::LEVEL_DARKGREEN => 0,
998
            self::LEVEL_LIGHTGREEN => 0,
999
            self::LEVEL_WHITE => 0,
1000
            self::LEVEL_LIGHTRED => 0,
1001
            self::LEVEL_DARKRED => 0,
1002
        ];
1003
1004
        $attemptInfoList = self::getExerciseAttemptInfo($exeId);
1005
1006
        foreach ($attemptInfoList as $attemptInfo) {
1007
            $oQuestion = new MultipleAnswerTrueFalseDegreeCertainty();
1008
            $oQuestion->read($attemptInfo['question_id']);
1009
            if ($oQuestion->type == MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY) {
1010
                $answerColor = self::getAnswerColor($exeId, $attemptInfo['question_id'], $attemptInfo['position']);
1011
                if ($answerColor) {
1012
                    $result[$answerColor]++;
1013
                }
1014
            }
1015
        }
1016
1017
        return $result;
1018
    }
1019
1020
    /**
1021
     * return an array of number of color for question type = MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY
1022
     * for each question category.
1023
     *
1024
     * e.g.
1025
     * [
1026
     *      (categoryId=)5 => [LEVEL_DARKGREEN => 3, LEVEL_WHITE => 5, LEVEL_LIGHTRED => 12]
1027
     *      (categoryId=)2 => [LEVEL_DARKGREEN => 8, LEVEL_LIGHTRED => 2, LEVEL_DARKTRED => 8]
1028
     *      (categoryId=)0 => [LEVEL_DARKGREEN => 1,
1029
     *          LEVEL_LIGHTGREEN => 2,
1030
     *          LEVEL_WHITE => 6,
1031
     *          LEVEL_LIGHTRED => 1,
1032
     *          LEVEL_DARKTRED => 9]
1033
     * ]
1034
     *
1035
     * @param int $exeId
1036
     *
1037
     * @return array
1038
     */
1039
    public static function getColorNumberListForAttemptByCategory($exeId)
1040
    {
1041
        $result = [];
1042
        $attemptInfoList = self::getExerciseAttemptInfo($exeId);
1043
1044
        foreach ($attemptInfoList as $attemptInfo) {
1045
            $oQuestion = new MultipleAnswerTrueFalseDegreeCertainty();
1046
            $oQuestion->read($attemptInfo['question_id']);
1047
            if ($oQuestion->type == MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY) {
1048
                $questionCategory = Testcategory::getCategoryForQuestion($attemptInfo['question_id']);
1049
1050
                if (!array_key_exists($questionCategory, $result)) {
1051
                    $result[$questionCategory] = [];
1052
                }
1053
1054
                $answerColor = self::getAnswerColor($exeId, $attemptInfo['question_id'], $attemptInfo['position']);
1055
                if ($answerColor && isset($result[$questionCategory])) {
1056
                    if (!isset($result[$questionCategory][$answerColor])) {
1057
                        $result[$questionCategory][$answerColor] = 0;
1058
                    }
1059
                    $result[$questionCategory][$answerColor]++;
1060
                }
1061
            }
1062
        }
1063
1064
        return $result;
1065
    }
1066
1067
    /**
1068
     * Return true if answer of $exeId, $questionId, $position is correct, otherwise return false.
1069
     *
1070
     * @param $exeId
1071
     * @param $questionId
1072
     * @param $position
1073
     *
1074
     * @return int
1075
     */
1076
    public static function getAnswerColor($exeId, $questionId, $position)
1077
    {
1078
        $attemptInfoList = self::getExerciseAttemptInfo($exeId, $questionId, $position);
1079
1080
        if (count($attemptInfoList) != 1) {
1081
            // havent got the answer
1082
            return 0;
1083
        }
1084
1085
        $answerCodes = $attemptInfoList[0]['answer'];
1086
1087
        // student answer
1088
        $splitAnswer = preg_split("/:/", $answerCodes);
1089
        // get correct answer option id
1090
        $correctAnswerOptionId = self::getCorrectAnswerOptionId($splitAnswer[0]);
1091
        if ($correctAnswerOptionId == 0) {
1092
            // error returning the correct answer option id
1093
            return 0;
1094
        }
1095
1096
        // get student answer option id
1097
        $studentAnswerOptionId = isset($splitAnswer[1]) ? $splitAnswer[1] : null;
1098
1099
        // we got the correct answer option id, let's compare ti with the student answer
1100
        $percentage = null;
1101
        if (isset($splitAnswer[2])) {
1102
            $percentage = self::getPercentagePosition($splitAnswer[2]);
1103
        }
1104
1105
        if ($studentAnswerOptionId == $correctAnswerOptionId) {
1106
            // yeah, student got correct answer
1107
            switch ($percentage) {
1108
                case 3:
1109
                    return self::LEVEL_WHITE;
1110
                case 4:
1111
                case 5:
1112
                    return self::LEVEL_LIGHTGREEN;
1113
                case 6:
1114
                case 7:
1115
                case 8:
1116
                    return self::LEVEL_DARKGREEN;
1117
                default:
1118
                    return 0;
1119
            }
1120
        } else {
1121
            // bummer, wrong answer dude
1122
            switch ($percentage) {
1123
                case 3:
1124
                    return self::LEVEL_WHITE;
1125
                case 4:
1126
                case 5:
1127
                    return self::LEVEL_LIGHTRED;
1128
                case 6:
1129
                case 7:
1130
                case 8:
1131
                    return self::LEVEL_DARKRED;
1132
                default:
1133
                    return 0;
1134
            }
1135
        }
1136
    }
1137
1138
    /**
1139
     * Return the position of certitude %age choose by student.
1140
     *
1141
     * @param $optionId
1142
     *
1143
     * @return int
1144
     */
1145
    public static function getPercentagePosition($optionId)
1146
    {
1147
        $tblAnswerOption = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION);
1148
        $optionId = (int) $optionId;
1149
        $sql = "SELECT position
1150
                FROM $tblAnswerOption
1151
                WHERE iid = $optionId";
1152
        $res = Database::query($sql);
1153
1154
        if (Database::num_rows($res) == 0) {
1155
            return 0;
1156
        }
1157
1158
        $data = Database::fetch_assoc($res);
1159
1160
        return $data['position'];
1161
    }
1162
1163
    /**
1164
     * return the correct id from c_quiz_question_option for question idAuto.
1165
     *
1166
     * @param $idAuto
1167
     *
1168
     * @return int
1169
     */
1170
    public static function getCorrectAnswerOptionId($idAuto)
1171
    {
1172
        $tblAnswer = Database::get_course_table(TABLE_QUIZ_ANSWER);
1173
        $idAuto = (int) $idAuto;
1174
        $sql = "SELECT correct FROM $tblAnswer
1175
                WHERE id_auto = $idAuto";
1176
1177
        $res = Database::query($sql);
1178
        $data = Database::fetch_assoc($res);
1179
        if (Database::num_rows($res) > 0) {
1180
            return $data['correct'];
1181
        } else {
1182
            return 0;
1183
        }
1184
    }
1185
1186
    /**
1187
     * return an array of exe info from track_e_attempt.
1188
     *
1189
     * @param int $exeId
1190
     * @param int $questionId
1191
     * @param int $position
1192
     *
1193
     * @return array
1194
     */
1195
    public static function getExerciseAttemptInfo($exeId, $questionId = -1, $position = -1)
1196
    {
1197
        $result = [];
1198
        $and = '';
1199
        $questionId = (int) $questionId;
1200
        $position = (int) $position;
1201
        $exeId = (int) $exeId;
1202
1203
        if ($questionId >= 0) {
1204
            $and .= " AND question_id = $questionId";
1205
        }
1206
        if ($position >= 0) {
1207
            $and .= " AND position = $position";
1208
        }
1209
1210
        $tblExeAttempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
1211
        $cId = api_get_course_int_id();
1212
        $sql = "SELECT * FROM $tblExeAttempt
1213
                WHERE c_id = $cId AND exe_id = $exeId $and";
1214
1215
        $res = Database::query($sql);
1216
        while ($data = Database::fetch_assoc($res)) {
1217
            $result[] = $data;
1218
        }
1219
1220
        return $result;
1221
    }
1222
1223
    /**
1224
     * @param int $exeId
1225
     *
1226
     * @return int
1227
     */
1228
    public static function getNumberOfQuestionsForExeId($exeId)
1229
    {
1230
        $tableTrackEExercise = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
1231
        $exeId = (int) $exeId;
1232
1233
        $sql = "SELECT exe_exo_id
1234
                FROM $tableTrackEExercise
1235
                WHERE exe_id = ".$exeId;
1236
        $res = Database::query($sql);
1237
        $data = Database::fetch_assoc($res);
1238
        if ($data) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $data of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1239
            $exerciseId = $data['exe_exo_id'];
1240
1241
            $objectExercise = new Exercise();
1242
            $objectExercise->read($exerciseId);
1243
1244
            return $objectExercise->getQuestionCount();
1245
        }
1246
1247
        return 0;
1248
    }
1249
1250
    /**
1251
     * Display student chart results for these question types.
1252
     *
1253
     * @param int      $exeId
1254
     * @param Exercise $objExercice
1255
     *
1256
     * @return string
1257
     */
1258
    public static function displayStudentsChartResults($exeId, $objExercice)
1259
    {
1260
        $numberOfQuestions = self::getNumberOfQuestionsForExeId($exeId);
1261
        $globalScoreList = self::getColorNumberListForAttempt($exeId);
1262
        $html = self::displayDegreeChart(
1263
            $globalScoreList,
1264
            600,
1265
            get_lang('YourOverallResultForTheTest'),
1266
            2,
1267
            0,
1268
            true,
1269
            false,
1270
            false,
1271
            $numberOfQuestions
1272
        );
1273
        $html .= '<br/>';
1274
1275
        $previousAttemptId = self::getPreviousAttemptId($exeId);
1276
        if ($previousAttemptId > 0) {
1277
            $previousAttemptScoreList = self::getColorNumberListForAttempt(
1278
                $previousAttemptId
1279
            );
1280
            $html .= self::displayDegreeChart(
1281
                $previousAttemptScoreList,
1282
                600,
1283
                get_lang('ForComparisonYourLastResultToThisTest'),
1284
                2
1285
            );
1286
            $html .= '<br/>';
1287
        }
1288
1289
        $list = self::getColorNumberListForAttemptByCategory($exeId);
1290
        $html .= self::displayDegreeChartByCategory(
1291
            $list,
1292
            get_lang('YourResultsByDiscipline'),
1293
            1,
1294
            $objExercice
1295
        );
1296
        $html .= '<br/>';
1297
1298
        return $html;
1299
    }
1300
1301
    /**
1302
     * send mail to student with degre certainty result test.
1303
     *
1304
     * @param int      $userId
1305
     * @param Exercise $objExercise
1306
     * @param int      $exeId
1307
     */
1308
    public static function sendQuestionCertaintyNotification($userId, $objExercise, $exeId)
1309
    {
1310
        $userInfo = api_get_user_info($userId);
1311
        $recipientName = api_get_person_name($userInfo['firstname'],
1312
            $userInfo['lastname'],
1313
            null,
1314
            PERSON_NAME_EMAIL_ADDRESS
1315
        );
1316
        $subject = "[".get_lang('DoNotReply')."] "
1317
            .html_entity_decode(get_lang('ResultAccomplishedTest')." \"".$objExercise->title."\"");
1318
1319
        // message sended to the student
1320
        $message = get_lang('Dear').' '.$recipientName.",<br /><br />";
1321
        $exerciseLink = "<a href='".api_get_path(WEB_CODE_PATH)."/exercise/result.php?show_headers=1&"
1322
            .api_get_cidreq()
1323
            ."&id=$exeId'>";
1324
        $exerciseTitle = $objExercise->title;
1325
1326
        $message .= sprintf(
1327
            get_lang('MessageQuestionCertainty'),
1328
            $exerciseTitle,
1329
            api_get_path(WEB_PATH),
1330
            $exerciseLink
1331
        );
1332
1333
        // show histogram
1334
        $message .= self::displayStudentsChartResults($exeId, $objExercise);
1335
        $message .= get_lang('KindRegards');
1336
        $message = api_preg_replace("/\\\n/", '', $message);
1337
1338
        MessageManager::send_message_simple($userId, $subject, $message);
1339
    }
1340
}
1341