displayDegreeChart()   F
last analyzed

Complexity

Conditions 23
Paths > 20000

Size

Total Lines 136
Code Lines 90

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 23
eloc 90
nc 208896
nop 9
dl 0
loc 136
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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