Passed
Push — 1.11.x ( bce6cd...c146d9 )
by Angel Fernando Quiroz
12:25
created

main/exercise/ReadingComprehension.php (1 issue)

1
0 ignored issues
show
It is not recommended to output anything before PHP's opening tag in non-template files.
Loading history...
2
<?php
3
4
/* For licensing terms, see /license.txt */
5
6
/**
7
 * Class ReadingComprehension.
8
 *
9
 * This class allows to instantiate an object of type READING_COMPREHENSION
10
 * extending the class question
11
 */
12
class ReadingComprehension extends UniqueAnswer
13
{
14
    public $typePicture = 'reading-comprehension.png';
15
    public $explanationLangVar = 'ReadingComprehension';
16
17
    /**
18
     * Defines the different speeds of scrolling for the reading window,
19
     * in words per minute. If 300 words text in 50w/m, then the moving
20
     * window will progress from top to bottom in 6 minutes.
21
     *
22
     * @var array
23
     */
24
    public static $speeds = [
25
        1 => 50,
26
        2 => 100,
27
        3 => 175,
28
        4 => 300,
29
        5 => 600,
30
    ];
31
32
    /**
33
     * The number of words in the question description (which serves as the
34
     * text to read).
35
     *
36
     * @var int
37
     */
38
    public $wordsCount = 0;
39
40
    /**
41
     * Number of words expected to show per refresh.
42
     *
43
     * @var int
44
     */
45
    public $expectedWordsPerRefresh = 0;
46
47
    /**
48
     * Refresh delay in seconds.
49
     *
50
     * @var int
51
     */
52
    public $refreshTime = 3;
53
54
    /**
55
     * Indicates how show the question list.
56
     * 1 = all in one page; 2 = one per page (default).
57
     *
58
     * @var int
59
     */
60
    private $exerciseType = 2;
61
62
    /**
63
     * Constructor.
64
     */
65
    public function __construct()
66
    {
67
        parent::__construct();
68
        $this->type = READING_COMPREHENSION;
69
        $this->isContent = $this->getIsContent();
70
    }
71
72
    public function processText($text)
73
    {
74
        // Refresh is set to 5s, but speed is in words per minute
75
        $wordsPerSecond = self::$speeds[$this->level] / 60;
76
        $this->expectedWordsPerRefresh = intval($wordsPerSecond * $this->refreshTime);
77
78
        if (empty($text)) {
79
            // We have an issue here... how do we treat this case?
80
            // For now, let's define a default case
81
            $text = get_lang('NoExercise');
82
        }
83
        $words = str_word_count($text, 2, '0..9');
84
        $indexes = array_keys($words);
85
86
        $tagEnd = '</span>';
87
        $tagStart = $tagEnd.'<span class="text-highlight">';
88
        $this->wordsCount = count($words);
89
90
        $turns = ceil(
91
            $this->wordsCount / $this->expectedWordsPerRefresh
92
        );
93
94
        $firstIndex = $indexes[0];
95
96
        for ($i = 1; $i <= $turns; $i++) {
97
            $text = substr_replace($text, $tagStart, $firstIndex, 0);
98
99
            if ($i * $this->expectedWordsPerRefresh <= count($words)) {
100
                $newIndex = $i * $this->expectedWordsPerRefresh;
101
                if (isset($indexes[$newIndex])) {
102
                    $nextFirstIndex = $indexes[$newIndex];
103
                    $firstIndex = $nextFirstIndex + (strlen($tagStart) * $i);
104
                }
105
            }
106
        }
107
108
        $pos = strpos($text, $tagEnd);
109
110
        $text = substr_replace($text, '', $pos, strlen($tagEnd));
111
        $text .= $tagEnd;
112
113
        $this->displayReading($this->wordsCount, $turns, $text);
114
    }
115
116
    /**
117
     * Returns total count of words of the text to read.
118
     *
119
     * @return int
120
     */
121
    public function getWordsCount()
122
    {
123
        $words = str_word_count($this->selectDescription(), 2, '0..9');
124
        $this->wordsCount = count($words);
125
126
        return $this->wordsCount;
127
    }
128
129
    /**
130
     * {@inheritdoc}
131
     */
132
    public function createForm(&$form, $exercise)
133
    {
134
        // Categories
135
        $tabCat = TestCategory::getCategoriesIdAndName();
136
        $form->addSelect('questionCategory', get_lang('Category'), $tabCat);
137
        // Advanced parameters
138
        $levels = self::get_default_levels();
139
        $form->addSelect('questionLevel', get_lang('Difficulty'), $levels);
140
        $form->addElement('hidden', 'answerType', READING_COMPREHENSION);
141
        $form->addTextarea('questionDescription', get_lang('Text'), ['rows' => 20]);
142
        // question name
143
        if (api_get_configuration_value('save_titles_as_html')) {
144
            $editorConfig = ['ToolbarSet' => 'TitleAsHtml'];
145
            $form->addHtmlEditor(
146
                'questionName',
147
                get_lang('Question'),
148
                false,
149
                false,
150
                $editorConfig,
151
                true
152
            );
153
        } else {
154
            $form->addText('questionName', get_lang('Question'), false);
155
        }
156
157
        // hidden values
158
        $form->addRule('questionName', get_lang('GiveQuestion'), 'required');
159
        $isContent = isset($_REQUEST['isContent']) ? (int) $_REQUEST['isContent'] : null;
160
161
        // default values
162
        $defaults = [];
163
        $defaults['questionName'] = $this->question;
164
        $defaults['questionDescription'] = $this->description;
165
        $defaults['questionLevel'] = $this->level;
166
        $defaults['questionCategory'] = $this->category;
167
168
        // Came from he question pool
169
        if (isset($_GET['fromExercise'])) {
170
            $form->setDefaults($defaults);
171
        }
172
173
        if (!isset($_GET['newQuestion']) || $isContent) {
174
            $form->setDefaults($defaults);
175
        }
176
    }
177
178
    /**
179
     * {@inheritdoc}
180
     */
181
    public static function get_default_levels()
182
    {
183
        return [
184
            1 => sprintf(get_lang('ReadingComprehensionLevelX'), self::$speeds[1]),
185
            2 => sprintf(get_lang('ReadingComprehensionLevelX'), self::$speeds[2]),
186
            3 => sprintf(get_lang('ReadingComprehensionLevelX'), self::$speeds[3]),
187
            4 => sprintf(get_lang('ReadingComprehensionLevelX'), self::$speeds[4]),
188
            5 => sprintf(get_lang('ReadingComprehensionLevelX'), self::$speeds[5]),
189
        ];
190
    }
191
192
    /**
193
     * @param int $type
194
     *
195
     * @return ReadingComprehension
196
     */
197
    public function setExerciseType($type)
198
    {
199
        $this->exerciseType = (int) $type;
200
201
        return $this;
202
    }
203
204
    /**
205
     * @param $wordsCount
206
     * @param $turns
207
     * @param $text
208
     */
209
    private function displayReading($wordsCount, $turns, $text)
210
    {
211
        $view = new Template('', false, false, false, true, false, false);
212
213
        $template = $view->get_template('exercise/reading_comprehension.tpl');
214
215
        $view->assign('id', $this->iid);
216
        $view->assign('text', nl2br($text));
217
        $view->assign('words_count', $wordsCount);
218
        $view->assign('turns', $turns);
219
        $view->assign('refresh_time', $this->refreshTime);
220
        $view->assign('exercise_type', $this->exerciseType);
221
        $view->display($template);
222
    }
223
}
224