Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
/**
18
 * This defines the states a question can be in.
19
 *
20
 * @package    moodlecore
21
 * @subpackage questionengine
22
 * @copyright  2010 The Open University
23
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24
 */
25
 
26
 
27
defined('MOODLE_INTERNAL') || die();
28
 
29
 
30
/**
31
 * An enumeration representing the states a question can be in after a
32
 * {@link question_attempt_step}.
33
 *
34
 * There are also some useful methods for testing and manipulating states.
35
 *
36
 * @copyright  2009 The Open University
37
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38
 */
39
abstract class question_state {
40
    /**#@+
41
     * Specific question_state instances.
42
     */
43
    public static $notstarted;
44
    public static $unprocessed;
45
    public static $todo;
46
    public static $invalid;
47
    public static $complete;
48
    public static $needsgrading;
49
    public static $finished;
50
    public static $gaveup;
51
    public static $gradedwrong;
52
    public static $gradedpartial;
53
    public static $gradedright;
54
    public static $manfinished;
55
    public static $mangaveup;
56
    public static $mangrwrong;
57
    public static $mangrpartial;
58
    public static $mangrright;
59
    /**#@+-*/
60
 
61
    protected function __construct() {
62
    }
63
 
64
    public static function init() {
65
        $us = new ReflectionClass('question_state');
66
        foreach ($us->getStaticProperties() as $name => $notused) {
67
            $class = 'question_state_' . $name;
68
            $states[$name] = new $class();
69
            self::$$name = $states[$name];
70
        }
71
    }
72
 
73
    /**
74
     * Get all the states in an array.
75
     *
76
     * @return question_state[] of question_state objects.
77
     */
78
    public static function get_all() {
79
        $states = array();
80
        $us = new ReflectionClass('question_state');
81
        foreach ($us->getStaticProperties() as $name => $notused) {
82
            $states[] = self::$$name;
83
        }
84
        return $states;
85
    }
86
 
87
    /**
88
     * Get all the states in an array.
89
     * @param string $summarystate one of the four summary states
90
     * inprogress, needsgrading, manuallygraded or autograded.
91
     * @return array of the corresponding states.
92
     */
93
    public static function get_all_for_summary_state($summarystate) {
94
        $states = array();
95
        foreach (self::get_all() as $state) {
96
            if ($state->get_summary_state() == $summarystate) {
97
                $states[] = $state;
98
            }
99
        }
100
        if (empty($states)) {
101
            throw new coding_exception('unknown summary state ' . $summarystate);
102
        }
103
        return $states;
104
    }
105
 
106
    /**
107
     * @return string convert this state to a string.
108
     */
109
    public function __toString() {
110
        return substr(get_class($this), 15);
111
    }
112
 
113
    /**
114
     * Get the instance of this class for a given state name.
115
     *
116
     * @param string $name a state name.
117
     * @return question_state|null the state with that name. (Null only in an exceptional case.)
118
     */
119
    public static function get(string $name): ?question_state {
120
        // In the past, there was a bug where null states got stored
121
        // in the database as an empty string, which was wrong because
122
        // the state column should be NOT NULL.
123
        // That is no longer possible, but we need to avoid exceptions
124
        // for people with old bad data in their database.
125
        if ($name === '') {
126
            debugging('Attempt to create a state from an empty string. ' .
127
                'This is probably a sign of bad data in your database. See MDL-80127.');
128
            return null;
129
        }
130
 
131
        return self::$$name;
132
    }
133
 
134
    /**
135
     * Is this state one of the ones that mean the question attempt is in progress?
136
     * That is, started, but no finished.
137
     * @return bool
138
     */
139
    public function is_active() {
140
        return false;
141
    }
142
 
143
    /**
144
     * Is this state one of the ones that mean the question attempt is finished?
145
     * That is, no further interaction possible, apart from manual grading.
146
     * @return bool
147
     */
148
    public function is_finished() {
149
        return true;
150
    }
151
 
152
    /**
153
     * Is this state one of the ones that mean the question attempt has been graded?
154
     * @return bool
155
     */
156
    public function is_graded() {
157
        return false;
158
    }
159
 
160
    /**
161
     * Is this state one of the ones that mean the question attempt has been graded?
162
     * @return bool
163
     */
164
    public function is_correct() {
165
        return false;
166
    }
167
 
168
    /**
169
     * Is this state one of the ones that mean the question attempt has been graded?
170
     * @return bool
171
     */
172
    public function is_partially_correct() {
173
        return false;
174
    }
175
 
176
    /**
177
     * Is this state one of the ones that mean the question attempt has been graded?
178
     * @return bool
179
     */
180
    public function is_incorrect() {
181
        return false;
182
    }
183
 
184
    /**
185
     * Is this state one of the ones that mean the question attempt has been graded?
186
     * @return bool
187
     */
188
    public function is_gave_up() {
189
        return false;
190
    }
191
 
192
    /**
193
     * Is this state one of the ones that mean the question attempt has had a manual comment added?
194
     * @return bool
195
     */
196
    public function is_commented() {
197
        return false;
198
    }
199
 
200
    /**
201
     * Each state can be categorised into one of four categories:
202
     * inprogress, needsgrading, manuallygraded or autograded.
203
     * @return string which category this state falls into.
204
     */
205
    public function get_summary_state() {
206
        if (!$this->is_finished()) {
207
            return 'inprogress';
208
        } else if ($this == self::$needsgrading) {
209
            return 'needsgrading';
210
        } else if ($this->is_commented()) {
211
            return 'manuallygraded';
212
        } else {
213
            return 'autograded';
214
        }
215
    }
216
 
217
    /**
218
     * Return the appropriate graded state based on a fraction. That is 0 or less
219
     * is $graded_incorrect, 1 is $graded_correct, otherwise it is $graded_partcorrect.
220
     * Appropriate allowance is made for rounding float values.
221
     *
222
     * @param number $fraction the grade, on the fraction scale.
223
     * @return question_state one of the state constants.
224
     */
225
    public static function graded_state_for_fraction($fraction) {
226
        if ($fraction < 0.000001) {
227
            return self::$gradedwrong;
228
        } else if ($fraction > 0.999999) {
229
            return self::$gradedright;
230
        } else {
231
            return self::$gradedpartial;
232
        }
233
    }
234
 
235
    /**
236
     * Return the appropriate manually graded state based on a fraction. That is 0 or less
237
     * is $manually_graded_incorrect, 1 is $manually_graded_correct, otherwise it is
238
     * $manually_graded_partcorrect. Appropriate allowance is made for rounding float values.
239
     *
240
     * @param number $fraction the grade, on the fraction scale.
241
     * @return int one of the state constants.
242
     */
243
    public static function manually_graded_state_for_fraction($fraction) {
244
        if (is_null($fraction)) {
245
            return self::$needsgrading;
246
        } else if ($fraction < 0.000001) {
247
            return self::$mangrwrong;
248
        } else if ($fraction > 0.999999) {
249
            return self::$mangrright;
250
        } else {
251
            return self::$mangrpartial;
252
        }
253
    }
254
 
255
    /**
256
     * Compute an appropriate state to move to after a manual comment has been
257
     * added to this state.
258
     * @param number $fraction the manual grade (if any) on the fraction scale.
259
     * @return int the new state.
260
     */
261
    public function corresponding_commented_state($fraction) {
262
        throw new coding_exception('Unexpected question state.');
263
    }
264
 
265
    /**
266
     * Return an appropriate CSS class name ''/'correct'/'partiallycorrect'/'incorrect',
267
     * for a state.
268
     * @return string
269
     */
270
    public function get_feedback_class() {
271
        return '';
272
    }
273
 
274
    /**
275
     * Return the name of an appropriate string to look up in the question
276
     * language pack for a state. This is used, for example, by
277
     * {@link question_behaviour::get_state_string()}. However, behaviours
278
     * sometimes change this default string for soemthing more specific.
279
     *
280
     * @param bool $showcorrectness Whether right/partial/wrong states should
281
     * be distinguised, or just treated as 'complete'.
282
     * @return string the name of a string that can be looked up in the 'question'
283
     *      lang pack, or used as a CSS class name, etc.
284
     */
285
    abstract public function get_state_class($showcorrectness);
286
 
287
    /**
288
     * The result of doing get_string on the result of {@link get_state_class()}.
289
     *
290
     * @param bool $showcorrectness Whether right/partial/wrong states should
291
     * be distinguised.
292
     * @return string a string from the lang pack that can be used in the UI.
293
     */
294
    public function default_string($showcorrectness) {
295
        return get_string($this->get_state_class($showcorrectness), 'question');
296
    }
297
}
298
 
299
 
300
/**#@+
301
 * Specific question_state subclasses.
302
 *
303
 * @copyright  2009 The Open University
304
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
305
 */
306
class question_state_notstarted extends question_state {
307
    public function is_finished() {
308
        return false;
309
    }
310
    public function get_state_class($showcorrectness) {
311
        throw new coding_exception('Unexpected question state.');
312
    }
313
}
314
class question_state_unprocessed extends question_state {
315
    public function is_finished() {
316
        return false;
317
    }
318
    public function get_state_class($showcorrectness) {
319
        throw new coding_exception('Unexpected question state.');
320
    }
321
}
322
class question_state_todo extends question_state {
323
    public function is_active() {
324
        return true;
325
    }
326
    public function is_finished() {
327
        return false;
328
    }
329
    public function get_state_class($showcorrectness) {
330
        return 'notyetanswered';
331
    }
332
}
333
class question_state_invalid extends question_state {
334
    public function is_active() {
335
        return true;
336
    }
337
    public function is_finished() {
338
        return false;
339
    }
340
    public function get_state_class($showcorrectness) {
341
        return 'invalidanswer';
342
    }
343
}
344
class question_state_complete extends question_state {
345
    public function is_active() {
346
        return true;
347
    }
348
    public function is_finished() {
349
        return false;
350
    }
351
    public function get_state_class($showcorrectness) {
352
        return 'answersaved';
353
    }
354
}
355
class question_state_needsgrading extends question_state {
356
    public function get_state_class($showcorrectness) {
357
        if ($showcorrectness) {
358
            return 'requiresgrading';
359
        } else {
360
            return 'complete';
361
        }
362
    }
363
    public function corresponding_commented_state($fraction) {
364
        return self::manually_graded_state_for_fraction($fraction);
365
    }
366
}
367
class question_state_finished extends question_state {
368
    public function get_state_class($showcorrectness) {
369
        return 'complete';
370
    }
371
    public function corresponding_commented_state($fraction) {
372
        return self::$manfinished;
373
    }
374
}
375
class question_state_gaveup extends question_state {
376
    public function is_gave_up() {
377
        return true;
378
    }
379
    public function get_feedback_class() {
380
        return 'incorrect';
381
    }
382
    public function get_state_class($showcorrectness) {
383
        return 'notanswered';
384
    }
385
    public function corresponding_commented_state($fraction) {
386
        if (is_null($fraction)) {
387
            return self::$mangaveup;
388
        } else {
389
            return self::manually_graded_state_for_fraction($fraction);
390
        }
391
    }
392
}
393
abstract class question_state_graded extends question_state {
394
    public function is_graded() {
395
        return true;
396
    }
397
    public function get_state_class($showcorrectness) {
398
        if ($showcorrectness) {
399
            return $this->get_feedback_class();
400
        } else {
401
            return 'complete';
402
        }
403
    }
404
    public function corresponding_commented_state($fraction) {
405
        return self::manually_graded_state_for_fraction($fraction);
406
    }
407
}
408
class question_state_gradedwrong extends question_state_graded {
409
    public function is_incorrect() {
410
        return true;
411
    }
412
    public function get_feedback_class() {
413
        return 'incorrect';
414
    }
415
}
416
class question_state_gradedpartial extends question_state_graded {
417
    public function is_graded() {
418
        return true;
419
    }
420
    public function is_partially_correct() {
421
        return true;
422
    }
423
    public function get_feedback_class() {
424
        return 'partiallycorrect';
425
    }
426
}
427
class question_state_gradedright extends question_state_graded {
428
    public function is_graded() {
429
        return true;
430
    }
431
    public function is_correct() {
432
        return true;
433
    }
434
    public function get_feedback_class() {
435
        return 'correct';
436
    }
437
}
438
class question_state_manfinished extends question_state_finished {
439
    public function is_commented() {
440
        return true;
441
    }
442
}
443
class question_state_mangaveup extends question_state_gaveup {
444
    public function is_commented() {
445
        return true;
446
    }
447
}
448
abstract class question_state_manuallygraded extends question_state_graded {
449
    public function is_commented() {
450
        return true;
451
    }
452
}
453
class question_state_mangrwrong extends question_state_manuallygraded {
454
    public function is_incorrect() {
455
        return false;
456
    }
457
    public function get_feedback_class() {
458
        return 'incorrect';
459
    }
460
}
461
class question_state_mangrpartial extends question_state_manuallygraded {
462
    public function is_partially_correct() {
463
        return true;
464
    }
465
    public function get_feedback_class() {
466
        return 'partiallycorrect';
467
    }
468
}
469
class question_state_mangrright extends question_state_manuallygraded {
470
    public function is_correct() {
471
        return true;
472
    }
473
    public function get_feedback_class() {
474
        return 'correct';
475
    }
476
}
477
/**#@-*/
478
question_state::init();