1 | <?php |
||
2 | /* For licensing terms, see /license.txt */ |
||
3 | |||
4 | use Chamilo\CoreBundle\Entity\TrackEAttempt; |
||
5 | |||
6 | /** |
||
7 | * Class QuestionOptionsEvaluationPlugin. |
||
8 | */ |
||
9 | class QuestionOptionsEvaluationPlugin extends Plugin |
||
10 | { |
||
11 | public const SETTING_ENABLE = 'enable'; |
||
12 | public const SETTING_MAX_SCORE = 'exercise_max_score'; |
||
13 | public const EXTRAFIELD_FORMULA = 'quiz_evaluation_formula'; |
||
14 | |||
15 | /** |
||
16 | * QuestionValuationPlugin constructor. |
||
17 | */ |
||
18 | protected function __construct() |
||
19 | { |
||
20 | $version = '1.0'; |
||
21 | $author = 'Angel Fernando Quiroz Campos'; |
||
22 | |||
23 | parent::__construct( |
||
24 | $version, |
||
25 | $author, |
||
26 | [ |
||
27 | self::SETTING_ENABLE => 'boolean', |
||
28 | self::SETTING_MAX_SCORE => 'text', |
||
29 | ] |
||
30 | ); |
||
31 | } |
||
32 | |||
33 | /** |
||
34 | * @return QuestionOptionsEvaluationPlugin|null |
||
35 | */ |
||
36 | public static function create() |
||
37 | { |
||
38 | static $result = null; |
||
39 | |||
40 | return $result ? $result : $result = new self(); |
||
41 | } |
||
42 | |||
43 | /** |
||
44 | * @param int $exerciseId |
||
45 | * @param int $iconSize |
||
46 | * |
||
47 | * @return string |
||
48 | */ |
||
49 | public static function filterModify($exerciseId, $iconSize = ICON_SIZE_SMALL) |
||
50 | { |
||
51 | $directory = basename(__DIR__); |
||
52 | $title = get_plugin_lang('plugin_title', self::class); |
||
53 | $enabled = api_get_plugin_setting('questionoptionsevaluation', 'enable'); |
||
54 | |||
55 | if ('true' !== $enabled) { |
||
56 | return ''; |
||
57 | } |
||
58 | |||
59 | return Display::url( |
||
60 | Display::return_icon('options_evaluation.png', $title, [], $iconSize), |
||
61 | api_get_path(WEB_PATH)."plugin/$directory/evaluation.php?exercise=$exerciseId", |
||
62 | [ |
||
63 | 'class' => 'ajax', |
||
64 | 'data-size' => 'md', |
||
65 | 'data-title' => get_plugin_lang('plugin_title', self::class), |
||
66 | ] |
||
67 | ); |
||
68 | } |
||
69 | |||
70 | public function install() |
||
71 | { |
||
72 | $this->createExtraField(); |
||
73 | } |
||
74 | |||
75 | public function uninstall() |
||
76 | { |
||
77 | $this->removeExtraField(); |
||
78 | } |
||
79 | |||
80 | /** |
||
81 | * @return Plugin |
||
82 | */ |
||
83 | public function performActionsAfterConfigure() |
||
84 | { |
||
85 | return $this; |
||
86 | } |
||
87 | |||
88 | /** |
||
89 | * @param int $formula |
||
90 | */ |
||
91 | public function saveFormulaForExercise($formula, Exercise $exercise) |
||
92 | { |
||
93 | $this->recalculateQuestionScore($formula, $exercise); |
||
94 | |||
95 | $extraFieldValue = new ExtraFieldValue('quiz'); |
||
96 | $extraFieldValue->save( |
||
97 | [ |
||
98 | 'item_id' => $exercise->iid, |
||
99 | 'variable' => self::EXTRAFIELD_FORMULA, |
||
100 | 'value' => $formula, |
||
101 | ] |
||
102 | ); |
||
103 | } |
||
104 | |||
105 | /** |
||
106 | * @param int $exerciseId |
||
107 | * |
||
108 | * @return int |
||
109 | */ |
||
110 | public function getFormulaForExercise($exerciseId) |
||
111 | { |
||
112 | $extraFieldValue = new ExtraFieldValue('quiz'); |
||
113 | $value = $extraFieldValue->get_values_by_handler_and_field_variable( |
||
114 | $exerciseId, |
||
115 | self::EXTRAFIELD_FORMULA |
||
116 | ); |
||
117 | |||
118 | if (empty($value)) { |
||
119 | return 0; |
||
120 | } |
||
121 | |||
122 | return (int) $value['value']; |
||
123 | } |
||
124 | |||
125 | /** |
||
126 | * @return int |
||
127 | */ |
||
128 | public function getMaxScore() |
||
129 | { |
||
130 | $max = $this->get(self::SETTING_MAX_SCORE); |
||
131 | |||
132 | if (!empty($max)) { |
||
133 | return (int) $max; |
||
134 | } |
||
135 | |||
136 | return 10; |
||
137 | } |
||
138 | |||
139 | /** |
||
140 | * @param int $trackId |
||
141 | * @param int $formula |
||
142 | * |
||
143 | * @throws \Doctrine\ORM\ORMException |
||
144 | * @throws \Doctrine\ORM\OptimisticLockException |
||
145 | * @throws \Doctrine\ORM\TransactionRequiredException |
||
146 | * |
||
147 | * @return float|int |
||
148 | */ |
||
149 | public function getResultWithFormula($trackId, $formula) |
||
150 | { |
||
151 | $em = Database::getManager(); |
||
152 | |||
153 | $eTrack = $em->find('ChamiloCoreBundle:TrackEExercises', $trackId); |
||
154 | |||
155 | $qTracks = $em |
||
156 | ->createQuery( |
||
157 | 'SELECT a FROM ChamiloCoreBundle:TrackEAttempt a |
||
158 | WHERE a.exeId = :id AND a.userId = :user AND a.cId = :course AND a.sessionId = :session' |
||
159 | ) |
||
160 | ->setParameters( |
||
161 | [ |
||
162 | 'id' => $eTrack->getExeId(), |
||
163 | 'course' => $eTrack->getCId(), |
||
164 | 'session' => $eTrack->getSessionId(), |
||
165 | 'user' => $eTrack->getExeUserId(), |
||
166 | ] |
||
167 | ) |
||
168 | ->getResult(); |
||
169 | |||
170 | $counts = ['correct' => 0, 'incorrect' => 0]; |
||
171 | |||
172 | /** @var TrackEAttempt $qTrack */ |
||
173 | foreach ($qTracks as $qTrack) { |
||
174 | if ($qTrack->getMarks() > 0) { |
||
175 | $counts['correct']++; |
||
176 | } elseif ($qTrack->getMarks() < 0) { |
||
177 | $counts['incorrect']++; |
||
178 | } |
||
179 | } |
||
180 | |||
181 | switch ($formula) { |
||
182 | case 1: |
||
183 | $result = $counts['correct'] - $counts['incorrect']; |
||
184 | break; |
||
185 | case 2: |
||
186 | $result = $counts['correct'] - $counts['incorrect'] / 2; |
||
187 | break; |
||
188 | case 3: |
||
189 | $result = $counts['correct'] - $counts['incorrect'] / 3; |
||
190 | break; |
||
191 | } |
||
192 | |||
193 | $score = ($result / count($qTracks)) * $this->getMaxScore(); |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
![]() |
|||
194 | |||
195 | return $score >= 0 ? $score : 0; |
||
196 | } |
||
197 | |||
198 | /** |
||
199 | * @param int $formula |
||
200 | */ |
||
201 | private function recalculateQuestionScore($formula, Exercise $exercise) |
||
202 | { |
||
203 | $tblQuestion = Database::get_course_table(TABLE_QUIZ_QUESTION); |
||
204 | $tblAnswer = Database::get_course_table(TABLE_QUIZ_ANSWER); |
||
205 | |||
206 | foreach ($exercise->questionList as $questionId) { |
||
207 | $question = Question::read($questionId, $exercise->course, false); |
||
208 | if (!in_array($question->selectType(), [UNIQUE_ANSWER, MULTIPLE_ANSWER])) { |
||
209 | continue; |
||
210 | } |
||
211 | |||
212 | $questionAnswers = new Answer($questionId, $exercise->course_id, $exercise); |
||
213 | $counts = array_count_values($questionAnswers->correct); |
||
214 | |||
215 | $questionPonderation = 0; |
||
216 | |||
217 | foreach ($questionAnswers->correct as $i => $isCorrect) { |
||
218 | if (!isset($questionAnswers->iid[$i])) { |
||
219 | continue; |
||
220 | } |
||
221 | |||
222 | $iid = $questionAnswers->iid[$i]; |
||
223 | |||
224 | if ($question->selectType() == MULTIPLE_ANSWER || 0 === $formula) { |
||
225 | $ponderation = 1 == $isCorrect ? 1 / $counts[1] : -1 / $counts[0]; |
||
226 | } else { |
||
227 | $ponderation = 1 == $isCorrect ? 1 : -1 / $formula; |
||
228 | } |
||
229 | |||
230 | if ($ponderation > 0) { |
||
231 | $questionPonderation += $ponderation; |
||
232 | } |
||
233 | |||
234 | Database::query("UPDATE $tblAnswer SET ponderation = $ponderation WHERE iid = $iid"); |
||
235 | } |
||
236 | |||
237 | Database::query("UPDATE $tblQuestion SET ponderation = $questionPonderation WHERE iid = {$question->iid}"); |
||
238 | } |
||
239 | } |
||
240 | |||
241 | /** |
||
242 | * Creates an extrafield. |
||
243 | */ |
||
244 | private function createExtraField() |
||
245 | { |
||
246 | $extraField = new ExtraField('quiz'); |
||
247 | |||
248 | if (false === $extraField->get_handler_field_info_by_field_variable(self::EXTRAFIELD_FORMULA)) { |
||
249 | $extraField |
||
250 | ->save( |
||
251 | [ |
||
252 | 'variable' => self::EXTRAFIELD_FORMULA, |
||
253 | 'field_type' => ExtraField::FIELD_TYPE_TEXT, |
||
254 | 'display_text' => $this->get_lang('EvaluationFormula'), |
||
255 | 'visible_to_self' => false, |
||
256 | 'changeable' => false, |
||
257 | ] |
||
258 | ); |
||
259 | } |
||
260 | } |
||
261 | |||
262 | /** |
||
263 | * Removes the extrafield . |
||
264 | */ |
||
265 | private function removeExtraField() |
||
266 | { |
||
267 | $extraField = new ExtraField('quiz'); |
||
268 | $value = $extraField->get_handler_field_info_by_field_variable(self::EXTRAFIELD_FORMULA); |
||
269 | |||
270 | if (false !== $value) { |
||
271 | $extraField->delete($value['id']); |
||
272 | } |
||
273 | } |
||
274 | } |
||
275 |