2 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
17 * @package backup-convert
18 * @copyright 2011 Darko Miletic <dmiletic@moodlerooms.com>
19 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22 defined('MOODLE_INTERNAL') or die('Direct access to this script is forbidden.');
24 require_once('cc_utils.php');
25 require_once('cc_general.php');
27 abstract class cc_xml_namespace
{
28 const xml
= 'http://www.w3.org/XML/1998/namespace';
31 abstract class cc_qti_metadata
{
33 const qmd_assessmenttype
= 'qmd_assessmenttype';
34 const qmd_scoretype
= 'qmd_scoretype';
35 const qmd_feedbackpermitted
= 'qmd_feedbackpermitted';
36 const qmd_hintspermitted
= 'qmd_hintspermitted';
37 const qmd_solutionspermitted
= 'qmd_solutionspermitted';
38 const qmd_timelimit
= 'qmd_timelimit';
39 const cc_allow_late_submission
= 'cc_allow_late_submission';
40 const cc_maxattempts
= 'cc_maxattempts';
41 const cc_profile
= 'cc_profile';
44 const cc_weighting
= 'cc_weighting';
45 const qmd_scoringpermitted
= 'qmd_scoringpermitted';
46 const qmd_computerscored
= 'qmd_computerscored';
47 const cc_question_category
= 'cc_question_category';
50 abstract class cc_qti_profiletype
{
51 const multiple_choice
= 'cc.multiple_choice.v0p1';
52 const multiple_response
= 'cc.multiple_response.v0p1';
53 const true_false
= 'cc.true_false.v0p1';
54 const field_entry
= 'cc.fib.v0p1';
55 const pattern_match
= 'cc.pattern_match.v0p1';
56 const essay
= 'cc.essay.v0p1';
60 * validates a profile value
61 * @param string $value
64 public static function valid($value) {
65 static $verification_values = array( self
::essay
,
67 self
::multiple_choice
,
68 self
::multiple_response
,
72 return in_array($value, $verification_values);
77 abstract class cc_qti_values
{
78 const exam_profile
= 'cc.exam.v0p1';
81 const Response
= 'Response';
82 const Solution
= 'Solution';
84 const Examination
= 'Examination';
85 const Percentage
= 'Percentage';
86 const unlimited
= 'unlimited';
87 const Single
= 'Single';
88 const Multiple
= 'Multiple';
89 const Ordered
= 'Ordered';
90 const Asterisk
= 'Asterisk';
92 const Dashline
= 'Dashline';
93 const Underline
= 'Underline';
94 const Decimal
= 'Decimal';
95 const Integer = 'Integer';
96 const Scientific
= 'Scientific';
97 const String = 'String';
98 const SCORE
= 'SCORE';
100 const Complete
= 'Complete';
101 const texttype
= 'text/plain';
102 const htmltype
= 'text/html';
105 abstract class cc_qti_tags
{
106 const questestinterop
= 'questestinterop';
107 const assessment
= 'assessment';
108 const qtimetadata
= 'qtimetadata';
109 const qtimetadatafield
= 'qtimetadatafield';
110 const fieldlabel
= 'fieldlabel';
111 const fieldentry
= 'fieldentry';
112 const section
= 'section';
113 const ident
= 'ident';
115 const title
= 'title';
116 const itemmetadata
= 'itemmetadata';
117 const presentation
= 'presentation';
118 const material
= 'material';
119 const mattext
= 'mattext';
120 const matref
= 'matref';
121 const matbreak
= 'matbreak';
122 const texttype
= 'texttype';
123 const response_lid
= 'response_lid';
124 const render_choice
= 'render_choice';
125 const response_label
= 'response_label';
126 const resprocessing
= 'resprocessing';
127 const outcomes
= 'outcomes';
128 const decvar
= 'decvar';
129 const respcondition
= 'respcondition';
130 const conditionvar
= 'conditionvar';
131 const other
= 'other';
132 const displayfeedback
= 'displayfeedback';
133 const maxvalue
= 'maxvalue';
134 const minvalue
= 'minvalue';
135 const varname
= 'varname';
136 const vartype
= 'vartype';
137 const continue_
= 'continue';
138 const feedbacktype
= 'feedbacktype';
139 const linkrefid
= 'linkrefid';
140 const varequal
= 'varequal';
141 const respident
= 'respident';
142 const itemfeedback
= 'itemfeedback';
143 const flow_mat
= 'flow_mat';
144 const rcardinality
= 'rcardinality';
145 const charset
= 'charset';
146 const label
= 'label';
148 const width
= 'width';
149 const height
= 'height';
152 const xml_lang
= 'lang';
153 const xml_space
= 'space';
154 const rubric
= 'rubric';
155 const altmaterial
= 'altmaterial';
156 const presentation_material
= 'presentation_material';
157 const t_class
= 'class';
158 const material_ref
= 'material_ref';
159 const rtiming
= 'rtiming';
160 const render_fib
= 'render_fib';
161 const shuffle
= 'shuffle';
162 const minnumber
= 'minnumber';
163 const maxnumber
= 'maxnumber';
164 const encoding
= 'encoding';
165 const maxchars
= 'maxchars';
166 const prompt
= 'prompt';
167 const fibtype
= 'fibtype';
169 const columns
= 'columns';
170 const labelrefid
= 'labelrefid';
171 const rshuffle
= 'rshuffle';
172 const match_group
= 'match_group';
173 const match_max
= 'match_max';
175 const response_str
= 'response_str';
176 const flow_label
= 'flow_label';
177 const setvar
= 'setvar';
178 const action
= 'action';
181 const case_
= 'case';
182 const varsubstring
= 'varsubstring';
184 const solution
= 'solution';
185 const feedbackstyle
= 'feedbackstyle';
186 const solutionmaterial
= 'solutionmaterial';
187 const hintmaterial
= 'hintmaterial';
190 class cc_question_metadata_base
{
194 protected $metadata = array();
197 * @param string $setting
198 * @param mixed $value
200 protected function set_setting($setting, $value = null) {
201 $this->metadata
[$setting] = $value;
205 * @param string $setting
208 protected function get_setting($setting) {
210 if (array_key_exists($setting, $this->metadata
)) {
211 $result = $this->metadata
[$setting];
217 * @param string $setting
218 * @param string $namespace
219 * @param string $value
221 protected function set_setting_wns($setting, $namespace, $value = null) {
222 $this->metadata
[$setting] = array($namespace => $value);
226 * @param string $setting
227 * @param boolean $value
229 protected function enable_setting_yesno($setting, $value = true) {
230 $svalue = $value ? cc_qti_values
::Yes
: cc_qti_values
::No
;
231 $this->set_setting($setting, $svalue);
235 * @param XMLGenericDocument $doc
236 * @param DOMNode $item
237 * @param string $namespace
239 public function generate_attributes(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
240 foreach ($this->metadata
as $attribute => $value) {
241 if (!is_null($value)) {
242 if (!is_array($value)) {
243 $doc->append_new_attribute_ns($item, $namespace, $attribute, $value);
246 $nval = current($value);
247 if (!is_null($nval)) {
248 $doc->append_new_attribute_ns($item, $ns, $attribute, $nval);
256 * @param XMLGenericDocument $doc
257 * @param DOMNode $item
258 * @param string $namespace
260 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
261 $qtimetadata = $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::qtimetadata
);
262 foreach ($this->metadata
as $label => $entry) {
263 if (!is_null($entry)) {
264 $qtimetadatafield = $doc->append_new_element_ns($qtimetadata, $namespace, cc_qti_tags
::qtimetadatafield
);
265 $doc->append_new_element_ns($qtimetadatafield, $namespace, cc_qti_tags
::fieldlabel
, $label);
266 $doc->append_new_element_ns($qtimetadatafield, $namespace, cc_qti_tags
::fieldentry
, $entry);
272 class cc_question_metadata
extends cc_question_metadata_base
{
274 public function set_category($value) {
275 $this->set_setting(cc_qti_metadata
::cc_question_category
, $value);
278 public function set_weighting($value) {
279 $this->set_setting(cc_qti_metadata
::cc_weighting
, $value);
282 public function enable_scoringpermitted($value = true) {
283 $this->enable_setting_yesno(cc_qti_metadata
::qmd_scoringpermitted
, $value);
286 public function enable_computerscored($value = true) {
287 $this->enable_setting_yesno(cc_qti_metadata
::qmd_computerscored
, $value);
292 * Constructs metadata
293 * @param string $profile
294 * @throws InvalidArgumentException
296 public function __construct($profile) {
297 if (!cc_qti_profiletype
::valid($profile)) {
298 throw new InvalidArgumentException('Invalid profile type!');
300 $this->set_setting(cc_qti_metadata
::cc_profile
, $profile);
301 $this->set_setting(cc_qti_metadata
::cc_question_category
);
302 $this->set_setting(cc_qti_metadata
::cc_weighting
);
303 $this->set_setting(cc_qti_metadata
::qmd_scoringpermitted
);
304 $this->set_setting(cc_qti_metadata
::qmd_computerscored
);
309 class cc_assesment_metadata
extends cc_question_metadata_base
{
311 public function enable_hints($value = true) {
312 $this->enable_setting_yesno(cc_qti_metadata
::qmd_hintspermitted
, $value);
315 public function enable_solutions($value = true) {
316 $this->enable_setting_yesno(cc_qti_metadata
::qmd_solutionspermitted
, $value);
319 public function enable_latesubmissions($value = true) {
320 $this->enable_setting_yesno(cc_qti_metadata
::cc_allow_late_submission
, $value);
323 public function enable_feedback($value = true) {
324 $this->enable_setting_yesno(cc_qti_metadata
::qmd_feedbackpermitted
, $value);
327 public function set_timelimit($value) {
328 $ivalue = (int)$value;
329 if (($ivalue < 0) ||
($ivalue > 527401)) {
330 throw new OutOfRangeException('Time limit value out of permitted range!');
333 $this->set_setting(cc_qti_metadata
::qmd_timelimit
, $value);
336 public function set_maxattempts($value) {
337 $valid_values = array(cc_qti_values
::Examination
, cc_qti_values
::unlimited
, 1, 2, 3, 4, 5);
338 if (!in_array($value, $valid_values)) {
339 throw new OutOfRangeException('Max attempts has invalid value');
342 $this->set_setting(cc_qti_metadata
::cc_maxattempts
, $value);
345 public function __construct() {
346 //prepared default values
347 $this->set_setting(cc_qti_metadata
::cc_profile
, cc_qti_values
::exam_profile
);
348 $this->set_setting(cc_qti_metadata
::qmd_assessmenttype
, cc_qti_values
::Examination
);
349 $this->set_setting(cc_qti_metadata
::qmd_scoretype
, cc_qti_values
::Percentage
);
350 //optional empty values
351 $this->set_setting(cc_qti_metadata
::qmd_feedbackpermitted
);
352 $this->set_setting(cc_qti_metadata
::qmd_hintspermitted
);
353 $this->set_setting(cc_qti_metadata
::qmd_solutionspermitted
);
354 $this->set_setting(cc_qti_metadata
::qmd_timelimit
);
355 $this->set_setting(cc_qti_metadata
::cc_allow_late_submission
);
356 $this->set_setting(cc_qti_metadata
::cc_maxattempts
);
361 class cc_assesment_mattext
extends cc_question_metadata_base
{
362 protected $value = null;
364 public function __construct($value = null) {
365 $this->set_setting(cc_qti_tags
::texttype
, cc_qti_values
::texttype
);
366 $this->set_setting(cc_qti_tags
::charset
);//, 'ascii-us');
367 $this->set_setting(cc_qti_tags
::label
);
368 $this->set_setting(cc_qti_tags
::uri
);
369 $this->set_setting(cc_qti_tags
::width
);
370 $this->set_setting(cc_qti_tags
::height
);
371 $this->set_setting(cc_qti_tags
::x0
);
372 $this->set_setting(cc_qti_tags
::y0
);
373 $this->set_setting_wns(cc_qti_tags
::xml_lang
, cc_xml_namespace
::xml
);
374 $this->set_setting_wns(cc_qti_tags
::xml_space
, cc_xml_namespace
::xml
);//, 'default');
375 $this->value
= $value;
378 public function set_label($value) {
379 $this->set_setting(cc_qti_tags
::label
, $value);
382 public function set_uri($value) {
383 $this->set_setting(cc_qti_tags
::uri
, $value);
386 public function set_width_height($width = null, $height = null) {
387 $this->set_setting(cc_qti_tags
::width
, $width);
388 $this->set_setting(cc_qti_tags
::height
, $height);
391 public function set_coor($x = null, $y = null) {
392 $this->set_setting(cc_qti_tags
::x0
, $x);
393 $this->set_setting(cc_qti_tags
::y0
, $y);
396 public function set_lang($lang = null) {
397 $this->set_setting_wns(cc_qti_tags
::xml_lang
, cc_xml_namespace
::xml
, $lang);
400 public function set_content($content, $type = cc_qti_values
::texttype
, $charset = null) {
401 $this->value
= $content;
402 $this->set_setting(cc_qti_tags
::texttype
, $type);
403 $this->set_setting(cc_qti_tags
::charset
, $charset);
406 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
407 $mattext = $doc->append_new_element_ns_cdata($item, $namespace, cc_qti_tags
::mattext
, $this->value
);
408 $this->generate_attributes($doc, $mattext, $namespace);
412 class cc_assesment_matref
{
413 protected $linkref = null;
415 public function __construct($linkref) {
416 $this->linkref
= $linkref;
419 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
420 $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::matref
, $this->linkref
);
421 $doc->append_new_attribute_ns($node, $namespace, cc_qti_tags
::linkrefid
, $this->linkref
);
425 class cc_assesment_response_matref
extends cc_assesment_matref
{
426 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
427 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::material_ref
);
428 $doc->append_new_attribute_ns($node, $namespace, cc_qti_tags
::linkrefid
, $this->linkref
);
432 class cc_assesment_matbreak
{
433 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
434 $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::matbreak
);
438 abstract class cc_assesment_material_base
extends cc_question_metadata_base
{
442 protected $mattag = null;
443 protected $tagname = null;
445 protected function set_tag_value($object) {
446 $this->mattag
= $object;
449 public function set_mattext(cc_assesment_mattext
$object) {
450 $this->set_tag_value($object);
453 public function set_matref(cc_assesment_matref
$object) {
454 $this->set_tag_value($object);
457 public function set_matbreak(cc_assesment_matbreak
$object) {
458 $this->set_tag_value($object);
461 public function set_lang($value) {
462 $this->set_setting_wns(cc_qti_tags
::xml_lang
, cc_xml_namespace
::xml
, $value);
465 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
466 $material = $doc->append_new_element_ns($item, $namespace, $this->tagname
);
467 $this->generate_attributes($doc, $material, $namespace);
468 if (!empty($this->mattag
)) {
469 $this->mattag
->generate($doc, $material, $namespace);
475 class cc_assesment_altmaterial
extends cc_assesment_material_base
{
476 public function __construct($value = null) {
477 $this->set_setting_wns(cc_qti_tags
::xml_lang
, cc_xml_namespace
::xml
);
478 $this->tagname
= cc_qti_tags
::altmaterial
;
482 class cc_assesment_material
extends cc_assesment_material_base
{
484 protected $altmaterial = null;
486 public function __construct($value = null) {
487 $this->set_setting(cc_qti_tags
::label
);
488 $this->set_setting_wns(cc_qti_tags
::xml_lang
, cc_xml_namespace
::xml
);
489 $this->tagname
= cc_qti_tags
::material
;
492 public function set_label($value) {
493 $this->set_setting(cc_qti_tags
::label
, $value);
496 public function set_altmaterial(cc_assesment_altmaterial
$object) {
497 $this->altmaterial
= $object;
500 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
501 $material = parent
::generate($doc, $item, $namespace);
502 if (!empty($this->altmaterial
)) {
503 $this->altmaterial
->generate($doc, $material, $namespace);
508 class cc_assesment_rubric_base
extends cc_question_metadata_base
{
510 protected $material = null;
512 public function set_material($object) {
513 $this->material
= $object;
516 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
517 $rubric = $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::rubric
);
518 if (!empty($this->material
)) {
519 $this->material
->generate($doc, $rubric, $namespace);
524 class cc_assesment_presentation_material_base
extends cc_question_metadata_base
{
525 protected $flowmats = array();
527 public function add_flow_mat($object) {
528 $this->flowmats
[] = $object;
531 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
532 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::presentation_material
);
533 if (!empty($this->flowmats
)) {
534 foreach ($this->flowmats
as $flow_mat) {
535 $flow_mat->generate($doc, $node, $namespace);
541 class cc_assesment_flow_mat_base
extends cc_question_metadata_base
{
543 protected $mattag = null;
545 protected function set_tag_value($object) {
546 $this->mattag
= $object;
549 public function set_flow_mat(cc_assesment_flow_mat_base
$object) {
550 $this->set_tag_value($object);
553 public function set_material(cc_assesment_material
$object) {
554 $this->set_tag_value($object);
557 public function set_material_ref(cc_assesment_matref
$object) {
558 $this->set_tag_value($object);
561 public function __construct($value = null) {
562 $this->set_setting(cc_qti_tags
::t_class
);
565 public function set_class($value) {
566 $this->set_setting(cc_qti_tags
::t_class
, $value);
569 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
570 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::flow_mat
);
571 $this->generate_attributes($doc, $node, $namespace);
572 if (!empty($this->mattag
)) {
573 $this->mattag
->generate($doc, $node, $namespace);
579 class cc_assesment_section
extends cc_question_metadata_base
{
583 protected $items = array();
585 public function __construct() {
586 $this->set_setting(cc_qti_tags
::ident
, cc_helpers
::uuidgen('I_'));
587 $this->set_setting(cc_qti_tags
::title
);
588 $this->set_setting_wns(cc_qti_tags
::xml_lang
, cc_xml_namespace
::xml
);
591 public function set_ident($value) {
592 $this->set_setting(cc_qti_tags
::ident
, $value);
595 public function set_title($value) {
596 $this->set_setting(cc_qti_tags
::title
, $value);
599 public function set_lang($value) {
600 $this->set_setting_wns(cc_qti_tags
::xml_lang
, cc_xml_namespace
::xml
, $value);
603 public function add_item(cc_assesment_section_item
$object) {
604 $this->items
[] = $object;
607 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
608 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::section
);
609 $this->generate_attributes($doc, $node, $namespace);
610 if (!empty($this->items
)) {
611 foreach ($this->items
as $item) {
612 $item->generate($doc, $node, $namespace);
618 class cc_assesment_itemmetadata
extends cc_question_metadata_base
{
619 public function add_metadata($object) {
620 $this->metadata
[] = $object;
623 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
624 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::itemmetadata
);
625 if (!empty($this->metadata
)) {
626 foreach ($this->metadata
as $metaitem) {
627 $metaitem->generate($doc, $node, $namespace);
633 class cc_assesment_decvartype
extends cc_question_metadata_base
{
635 public function __construct() {
636 $this->set_setting(cc_qti_tags
::varname
, cc_qti_values
::SCORE
);
637 $this->set_setting(cc_qti_tags
::vartype
, cc_qti_values
::Integer);
638 $this->set_setting(cc_qti_tags
::minvalue
);
639 $this->set_setting(cc_qti_tags
::maxvalue
);
642 public function set_vartype($value) {
643 $this->set_setting(cc_qti_tags
::vartype
, $value);
646 public function set_limits($min = null, $max = null) {
647 $this->set_setting(cc_qti_tags
::minvalue
, $min);
648 $this->set_setting(cc_qti_tags
::maxvalue
, $max);
651 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
652 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::decvar
);
653 $this->generate_attributes($doc, $node, $namespace);
658 class cc_assignment_conditionvar_othertype
extends cc_question_metadata_base
{
659 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
660 $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::other
);
664 class cc_assignment_conditionvar_varequaltype
extends cc_question_metadata_base
{
665 protected $tagname = null;
666 protected $answerid = null;
668 public function __construct($value = null) {
669 if (is_null($value)) {
670 throw new InvalidArgumentException('Must not pass null!');
672 $this->answerid
= $value;
673 $this->set_setting(cc_qti_tags
::respident
);
674 $this->set_setting(cc_qti_tags
::case_
);//, cc_qti_values::No );
675 $this->tagname
= cc_qti_tags
::varequal
;
678 public function set_respident($value) {
679 $this->set_setting(cc_qti_tags
::respident
, $value);
682 public function enable_case($value = true) {
683 $this->enable_setting_yesno(cc_qti_tags
::case_
, $value);
686 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
687 $node = $doc->append_new_element_ns($item, $namespace, $this->tagname
, $this->answerid
);
688 $this->generate_attributes($doc, $node, $namespace);
692 class cc_assignment_conditionvar_varsubstringtype
extends cc_assignment_conditionvar_varequaltype
{
693 public function __construct($value) {
694 parent
::__construct($value);
695 $this->tagname
= cc_qti_tags
::varsubstring
;
700 class cc_assignment_conditionvar_andtype
extends cc_question_metadata_base
{
701 protected $nots = array();
702 protected $varequals = array();
704 public function set_not(cc_assignment_conditionvar_varequaltype
$object) {
705 $this->nots
[] = $object;
708 public function set_varequal(cc_assignment_conditionvar_varequaltype
$object) {
709 $this->varequals
[] = $object;
712 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
713 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::and_
);
714 if (!empty($this->nots
)) {
715 foreach ($this->nots
as $notv) {
716 $not = $doc->append_new_element_ns($node, $namespace, cc_qti_tags
::not_
);
717 $notv->generate($doc, $not, $namespace);
721 if (!empty($this->varequals
)) {
722 foreach ($this->varequals
as $varequal) {
723 $varequal->generate($doc, $node, $namespace);
729 class cc_assignment_conditionvar
extends cc_question_metadata_base
{
732 * @var cc_assignment_conditionvar_andtype
734 protected $and = null;
736 * @var cc_assignment_conditionvar_othertype
738 protected $other = null;
742 protected $varequal = array();
744 * @var cc_assignment_conditionvar_varsubstringtype
746 protected $varsubstring = null;
748 public function set_and(cc_assignment_conditionvar_andtype
$object) {
749 $this->and = $object;
752 public function set_other(cc_assignment_conditionvar_othertype
$object) {
753 $this->other
= $object;
756 public function set_varequal(cc_assignment_conditionvar_varequaltype
$object) {
757 $this->varequal
[] = $object;
760 public function set_varsubstring(cc_assignment_conditionvar_varsubstringtype
$object) {
761 $this->varsubstring
= $object;
764 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
765 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::conditionvar
);
767 if (!empty($this->and)) {
768 $this->and->generate($doc, $node, $namespace);
771 if (!empty($this->other
)) {
772 $this->other
->generate($doc, $node, $namespace);
775 if (!empty($this->varequal
)) {
776 foreach ($this->varequal
as $varequal) {
777 $varequal->generate($doc, $node, $namespace);
781 if (!empty($this->varsubstring
)) {
782 $this->varsubstring
->generate($doc, $node, $namespace);
787 class cc_assignment_displayfeedbacktype
extends cc_question_metadata_base
{
788 public function __construct() {
789 $this->set_setting(cc_qti_tags
::feedbacktype
);
790 $this->set_setting(cc_qti_tags
::linkrefid
);
793 public function set_feedbacktype($value) {
794 $this->set_setting(cc_qti_tags
::feedbacktype
, $value);
797 public function set_linkrefid($value) {
798 $this->set_setting(cc_qti_tags
::linkrefid
, $value);
801 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
802 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::displayfeedback
);
803 $this->generate_attributes($doc, $node, $namespace);
808 class cc_assignment_setvartype
extends cc_question_metadata_base
{
812 protected $tagvalue = null;
814 public function __construct($tagvalue = 100) {
815 $this->set_setting(cc_qti_tags
::varname
, cc_qti_values
::SCORE
);
816 $this->set_setting(cc_qti_tags
::action
, cc_qti_values
::Set
);
817 $this->tagvalue
= $tagvalue;
820 public function set_varname($value) {
821 $this->set_setting(cc_qti_tags
::varname
, $value);
824 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
825 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::setvar
, $this->tagvalue
);
826 $this->generate_attributes($doc, $node, $namespace);
830 class cc_assesment_respconditiontype
extends cc_question_metadata_base
{
832 * @var cc_assignment_conditionvar
834 protected $conditionvar = null;
835 protected $setvar = array();
836 protected $displayfeedback = array();
838 public function __construct() {
839 $this->set_setting(cc_qti_tags
::title
);
840 $this->set_setting(cc_qti_tags
::continue_
, cc_qti_values
::No
);
843 public function set_title($value) {
844 $this->set_setting(cc_qti_tags
::title
, $value);
847 public function enable_continue($value = true) {
848 $this->enable_setting_yesno(cc_qti_tags
::continue_
, $value);
851 public function set_conditionvar(cc_assignment_conditionvar
$object) {
852 $this->conditionvar
= $object;
855 public function add_setvar(cc_assignment_setvartype
$object) {
856 $this->setvar
[] = $object;
859 public function add_displayfeedback(cc_assignment_displayfeedbacktype
$object) {
860 $this->displayfeedback
[] = $object;
863 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
864 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::respcondition
);
865 $this->generate_attributes($doc, $node, $namespace);
867 if (!empty($this->conditionvar
)) {
868 $this->conditionvar
->generate($doc, $node, $namespace);
871 if (!empty($this->setvar
)) {
872 foreach ($this->setvar
as $setvar) {
873 $setvar->generate($doc, $node, $namespace);
877 if (!empty($this->displayfeedback
)) {
878 foreach ($this->displayfeedback
as $displayfeedback) {
879 $displayfeedback->generate($doc, $node, $namespace);
886 class cc_assesment_resprocessingtype
extends cc_question_metadata_base
{
888 * @var cc_assesment_decvartype
890 protected $decvar = null;
894 protected $respconditions = array();
896 public function set_decvar(cc_assesment_decvartype
$object) {
897 $this->decvar
= $object;
900 public function add_respcondition(cc_assesment_respconditiontype
$object) {
901 $this->respconditions
[] = $object;
904 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
905 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::resprocessing
);
906 $outcomes = $doc->append_new_element_ns($node, $namespace, cc_qti_tags
::outcomes
);
907 if (!empty($this->decvar
)) {
908 $this->decvar
->generate($doc, $outcomes, $namespace);
910 if (!empty($this->respconditions
)) {
911 foreach ($this->respconditions
as $rcond) {
912 $rcond->generate($doc, $node, $namespace);
919 class cc_assesment_itemfeedback_shintmaterial_base
extends cc_question_metadata_base
{
923 protected $tagname = null;
927 protected $flow_mats = array();
931 protected $materials = array();
934 * @param cc_assesment_flow_mattype $object
936 public function add_flow_mat(cc_assesment_flow_mattype
$object) {
937 $this->flow_mats
[] = $object;
941 * @param cc_assesment_material $object
943 public function add_material(cc_assesment_material
$object) {
944 $this->materials
[] = $object;
947 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
948 $node = $doc->append_new_element_ns($item, $namespace, $this->tagname
);
950 if (!empty($this->flow_mats
)) {
951 foreach ($this->flow_mats
as $flow_mat) {
952 $flow_mat->generate($doc, $node, $namespace);
956 if (!empty($this->materials
)) {
957 foreach ($this->materials
as $material) {
958 $material->generate($doc, $node, $namespace);
964 class cc_assesment_itemfeedback_hintmaterial
extends cc_assesment_itemfeedback_shintmaterial_base
{
965 public function __construct() {
966 $this->tagname
= cc_qti_tags
::hint
;
970 class cc_assesment_itemfeedback_solutionmaterial
extends cc_assesment_itemfeedback_shintmaterial_base
{
971 public function __construct() {
972 $this->tagname
= cc_qti_tags
::solutionmaterial
;
976 class cc_assesment_itemfeedback_shintype_base
extends cc_question_metadata_base
{
980 protected $tagname = null;
984 protected $items = array();
986 public function __construct() {
987 $this->set_setting(cc_qti_tags
::feedbackstyle
, cc_qti_values
::Complete
);
990 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
991 $node = $doc->append_new_element_ns($item, $namespace, $this->tagname
);
992 $this->generate_attributes($doc, $node, $namespace);
994 if (!empty($this->items
)) {
995 foreach ($this->items
as $telement) {
996 $telement->generate($doc, $node, $namespace);
1002 class cc_assesment_itemfeedback_solutiontype
extends cc_assesment_itemfeedback_shintype_base
{
1003 public function __construct() {
1004 parent
::__construct();
1005 $this->tagname
= cc_qti_tags
::solution
;
1009 * @param cc_assesment_itemfeedback_solutionmaterial $object
1011 public function add_solutionmaterial(cc_assesment_itemfeedback_solutionmaterial
$object) {
1012 $this->items
[] = $object;
1016 class cc_assesment_itemfeedbac_hinttype
extends cc_assesment_itemfeedback_shintype_base
{
1017 public function __construct() {
1018 parent
::__construct();
1019 $this->tagname
= cc_qti_tags
::hint
;
1023 * @param cc_assesment_itemfeedback_hintmaterial $object
1025 public function add_hintmaterial(cc_assesment_itemfeedback_hintmaterial
$object) {
1026 $this->items
[] = $object;
1030 class cc_assesment_itemfeedbacktype
extends cc_question_metadata_base
{
1032 * @var cc_assesment_flow_mattype
1034 protected $flow_mat = null;
1036 * @var cc_assesment_material
1038 protected $material = null;
1040 * @var cc_assesment_itemfeedback_solutiontype
1042 protected $solution = null;
1043 protected $hint = null;
1045 public function __construct() {
1046 $this->set_setting(cc_qti_tags
::ident
, cc_helpers
::uuidgen('I_'));
1047 $this->set_setting(cc_qti_tags
::title
);
1051 * @param string $value
1053 public function set_ident($value) {
1054 $this->set_setting(cc_qti_tags
::ident
, $value);
1058 * @param string $value
1060 public function set_title($value) {
1061 $this->set_setting(cc_qti_tags
::title
, $value);
1065 * @param cc_assesment_flow_mattype $object
1067 public function set_flow_mat(cc_assesment_flow_mattype
$object) {
1068 $this->flow_mat
= $object;
1072 * @param cc_assesment_material $object
1074 public function set_material(cc_assesment_material
$object) {
1075 $this->material
= $object;
1079 * @param cc_assesment_itemfeedback_solutiontype $object
1081 public function set_solution(cc_assesment_itemfeedback_solutiontype
$object) {
1082 $this->solution
= $object;
1085 public function set_hint($object) {
1086 $this->hint
= $object;
1089 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
1090 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::itemfeedback
);
1091 $this->generate_attributes($doc, $node, $namespace);
1093 if (!empty($this->flow_mat
) && empty($this->material
)) {
1094 $this->flow_mat
->generate($doc, $node, $namespace);
1097 if (!empty($this->material
) && empty($this->flow_mat
)) {
1098 $this->material
->generate($doc, $node, $namespace);
1101 if (!empty($this->solution
)) {
1102 $this->solution
->generate($doc, $node, $namespace);
1105 if (!empty($this->itemfeedback
)) {
1106 $this->itemfeedback
->generate($doc, $node, $namespace);
1111 class cc_assesment_section_item
extends cc_assesment_section
{
1114 * @var cc_assesment_itemmetadata
1116 protected $itemmetadata = null;
1118 * @var cc_assesment_presentation
1120 protected $presentation = null;
1121 protected $resprocessing = array();
1122 protected $itemfeedback = array();
1124 public function set_itemmetadata(cc_assesment_itemmetadata
$object) {
1125 $this->itemmetadata
= $object;
1128 public function set_presentation(cc_assesment_presentation
$object) {
1129 $this->presentation
= $object;
1132 public function add_resprocessing(cc_assesment_resprocessingtype
$object) {
1133 $this->resprocessing
[] = $object;
1136 public function add_itemfeedback(cc_assesment_itemfeedbacktype
$object) {
1137 $this->itemfeedback
[] = $object;
1140 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
1141 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::item
);
1142 $this->generate_attributes($doc, $node, $namespace);
1144 if (!empty($this->itemmetadata
)) {
1145 $this->itemmetadata
->generate($doc, $node, $namespace);
1148 if (!empty($this->presentation
)) {
1149 $this->presentation
->generate($doc, $node, $namespace);
1152 if (!empty($this->resprocessing
)) {
1153 foreach ($this->resprocessing
as $resprocessing) {
1154 $resprocessing->generate($doc, $node, $namespace);
1158 if (!empty($this->itemfeedback
)) {
1159 foreach ($this->itemfeedback
as $itemfeedback) {
1160 $itemfeedback->generate($doc, $node, $namespace);
1166 class cc_assesment_render_choicetype
extends cc_question_metadata_base
{
1170 protected $materials = array();
1175 protected $material_refs = array();
1180 protected $response_labels = array();
1184 protected $flow_labels = array();
1186 public function __construct() {
1187 $this->set_setting(cc_qti_tags
::shuffle
, cc_qti_values
::No
);
1188 $this->set_setting(cc_qti_tags
::minnumber
);
1189 $this->set_setting(cc_qti_tags
::maxnumber
);
1192 public function add_material(cc_assesment_material
$object) {
1193 $this->materials
[] = $object;
1196 public function add_material_ref(cc_assesment_response_matref
$object) {
1197 $this->material_refs
[] = $object;
1200 public function add_response_label(cc_assesment_response_labeltype
$object) {
1201 $this->response_labels
[] = $object;
1204 public function add_flow_label($object) {
1205 $this->flow_labels
[] = $object;
1208 public function enable_shuffle($value = true) {
1209 $this->enable_setting_yesno(cc_qti_tags
::shuffle
, $value);
1212 public function set_limits($min = null, $max = null) {
1213 $this->set_setting(cc_qti_tags
::minnumber
, $min);
1214 $this->set_setting(cc_qti_tags
::maxnumber
, $max);
1217 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
1218 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::render_choice
);
1219 $this->generate_attributes($doc, $node, $namespace);
1221 if (!empty($this->materials
)) {
1222 foreach ($this->materials
as $mattag) {
1223 $mattag->generate($doc, $node, $namespace);
1227 if (!empty($this->material_refs
)) {
1228 foreach ($this->material_refs
as $matreftag) {
1229 $matreftag->generate($doc, $node, $namespace);
1233 if (!empty($this->response_labels
)) {
1234 foreach ($this->response_labels
as $resplabtag) {
1235 $resplabtag->generate($doc, $node, $namespace);
1239 if (!empty($this->flow_labels
)) {
1240 foreach ($this->flow_labels
as $flowlabtag) {
1241 $flowlabtag->generate($doc, $node, $namespace);
1248 class cc_assesment_flow_mattype
extends cc_question_metadata_base
{
1251 * @var cc_assesment_material
1253 protected $material = null;
1255 * @var cc_assesment_response_matref
1257 protected $material_ref = null;
1259 * @var cc_assesment_flow_mattype
1261 protected $flow_mat = null;
1263 public function __construct() {
1264 $this->set_setting(cc_qti_tags
::t_class
);
1267 public function set_class($value) {
1268 $this->set_setting(cc_qti_tags
::t_class
, $value);
1271 public function set_material(cc_assesment_material
$object) {
1272 $this->material
= $object;
1275 public function set_material_ref(cc_assesment_response_matref
$object) {
1276 $this->material_ref
= $object;
1279 public function set_flow_mat(cc_assesment_flow_mattype
$object) {
1280 $this->flow_mat
= $object;
1283 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
1284 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::flow_mat
);
1285 $this->generate_attributes($doc, $node, $namespace);
1287 if (!empty($this->flow_mat
)) {
1288 $this->flow_mat
->generate($doc, $node, $namespace);
1291 if (!empty($this->material
)) {
1292 $this->material
->generate($doc, $node, $namespace);
1295 if (!empty($this->material_ref
)) {
1296 $this->material_ref
->generate($doc, $node, $namespace);
1301 class cc_assesment_response_labeltype
extends cc_question_metadata_base
{
1303 * @var cc_assesment_material
1305 protected $material = null;
1308 * @var cc_assesment_response_matref
1310 protected $material_ref = null;
1313 * @var cc_assesment_flow_mattype
1315 protected $flow_mat = null;
1317 public function __construct() {
1318 $this->set_setting(cc_qti_tags
::ident
, cc_helpers
::uuidgen('I_'));
1319 $this->set_setting(cc_qti_tags
::labelrefid
);
1320 $this->set_setting(cc_qti_tags
::rshuffle
);
1321 $this->set_setting(cc_qti_tags
::match_group
);
1322 $this->set_setting(cc_qti_tags
::match_max
);
1325 public function set_ident($value) {
1326 $this->set_setting(cc_qti_tags
::ident
, $value);
1329 public function get_ident() {
1330 return $this->get_setting(cc_qti_tags
::ident
);
1333 public function set_labelrefid($value) {
1334 $this->set_setting(cc_qti_tags
::labelrefid
, $value);
1337 public function enable_rshuffle($value = true) {
1338 $this->enable_setting_yesno(cc_qti_tags
::rshuffle
, $value);
1341 public function set_match_group($value) {
1342 $this->set_setting(cc_qti_tags
::match_group
, $value);
1345 public function set_match_max($value) {
1346 $this->set_setting(cc_qti_tags
::match_max
, $value);
1349 public function set_material(cc_assesment_material
$object) {
1350 $this->material
= $object;
1353 public function set_material_ref(cc_assesment_response_matref
$object) {
1354 $this->material_ref
= $object;
1357 public function set_flow_mat(cc_assesment_flow_mattype
$object) {
1358 $this->flow_mat
= $object;
1361 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
1362 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::response_label
);
1363 $this->generate_attributes($doc, $node, $namespace);
1365 if (!empty($this->material
)) {
1366 $this->material
->generate($doc, $node, $namespace);
1369 if (!empty($this->material_ref
)) {
1370 $this->material_ref
->generate($doc, $node, $namespace);
1373 if (!empty($this->flow_mat
)) {
1374 $this->flow_mat
->generate($doc, $node, $namespace);
1379 class cc_assesment_flow_labeltype
extends cc_question_metadata_base
{
1381 * @var cc_assesment_flow_labeltype
1383 protected $flow_label = null;
1385 * @var cc_assesment_response_labeltype
1387 protected $response_label = null;
1389 public function __construct() {
1390 $this->set_setting(cc_qti_tags
::t_class
);
1393 public function set_class($value) {
1394 $this->set_setting(cc_qti_tags
::t_class
, $value);
1397 public function set_flow_label(cc_assesment_flow_labeltype
$object) {
1398 $this->flow_label
= $object;
1401 public function set_response_label(cc_assesment_response_labeltype
$object) {
1402 $this->response_label
= $object;
1405 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
1406 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::flow_label
);
1407 $this->generate_attributes($doc, $node, $namespace);
1409 if (!empty($this->material
)) {
1410 $this->material
->generate($doc, $node, $namespace);
1413 if (!empty($this->material_ref
)) {
1414 $this->material_ref
->generate($doc, $node, $namespace);
1417 if (!empty($this->response_label
)) {
1418 $this->response_label
->generate($doc, $node, $namespace);
1421 if (!empty($this->flow_label
)) {
1422 $this->flow_label
->generate($doc, $node, $namespace);
1429 class cc_assesment_render_fibtype
extends cc_question_metadata_base
{
1431 * @var cc_assesment_material
1433 protected $material = null;
1436 * @var cc_assesment_response_matref
1438 protected $material_ref = null;
1440 * @var cc_assesment_response_labeltype
1442 protected $response_label = null;
1445 * Enter description here ...
1448 protected $flow_label = null;
1451 public function __construct() {
1452 $this->set_setting(cc_qti_tags
::encoding
);
1453 $this->set_setting(cc_qti_tags
::charset
);
1454 $this->set_setting(cc_qti_tags
::rows
);
1455 $this->set_setting(cc_qti_tags
::columns
);
1456 $this->set_setting(cc_qti_tags
::maxchars
);
1457 $this->set_setting(cc_qti_tags
::minnumber
);
1458 $this->set_setting(cc_qti_tags
::maxnumber
);
1459 $this->set_setting(cc_qti_tags
::prompt
, cc_qti_values
::Box
);
1460 $this->set_setting(cc_qti_tags
::fibtype
, cc_qti_values
::String);
1463 public function set_encoding($value) {
1464 $this->set_setting(cc_qti_tags
::encoding
, $value);
1466 public function set_charset($value) {
1467 $this->set_setting(cc_qti_tags
::charset
, $value);
1470 public function set_rows($value) {
1471 $this->set_setting(cc_qti_tags
::rows
, $value);
1474 public function set_columns($value) {
1475 $this->set_setting(cc_qti_tags
::columns
, $value);
1478 public function set_maxchars($value) {
1479 $this->set_setting(cc_qti_tags
::columns
, $value);
1482 public function set_limits($min = null, $max = null) {
1483 $this->set_setting(cc_qti_tags
::minnumber
, $min);
1484 $this->set_setting(cc_qti_tags
::maxnumber
, $max);
1487 public function set_prompt($value) {
1488 $this->set_setting(cc_qti_tags
::prompt
, $value);
1491 public function set_fibtype($value) {
1492 $this->set_setting(cc_qti_tags
::fibtype
, $value);
1495 public function set_material(cc_assesment_material
$object) {
1496 $this->material
= $object;
1499 public function set_material_ref(cc_assesment_response_matref
$object) {
1500 $this->material_ref
= $object;
1503 public function set_response_label(cc_assesment_response_labeltype
$object) {
1504 $this->response_label
= $object;
1507 public function set_flow_label($object) {
1508 $this->flow_label
= $object;
1511 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
1512 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::render_fib
);
1513 $this->generate_attributes($doc, $node, $namespace);
1515 if (!empty($this->material
) && empty($this->material_ref
)) {
1516 $this->material
->generate($doc, $node, $namespace);
1519 if (!empty($this->material_ref
) && empty($this->material
)) {
1520 $this->material_ref
->generate($doc, $node, $namespace);
1523 if (!empty($this->response_label
)) {
1524 $this->response_label
->generate($doc, $node, $namespace);
1527 if (!empty($this->flow_label
)) {
1528 $this->flow_label
->generate($doc, $node, $namespace);
1533 class cc_response_lidtype
extends cc_question_metadata_base
{
1537 protected $tagname = null;
1539 * @var cc_assesment_material
1541 protected $material = null;
1544 * @var cc_assesment_response_matref
1546 protected $material_ref = null;
1549 * @var cc_assesment_render_choicetype
1551 protected $render_choice = null;
1554 * @var cc_assesment_render_fibtype
1556 protected $render_fib = null;
1558 public function __construct() {
1559 $this->set_setting(cc_qti_tags
::rcardinality
, cc_qti_values
::Single
);
1560 $this->set_setting(cc_qti_tags
::rtiming
);
1561 $this->set_setting(cc_qti_tags
::ident
, cc_helpers
::uuidgen('I_'));
1562 $this->tagname
= cc_qti_tags
::response_lid
;
1565 public function set_rcardinality($value) {
1566 $this->set_setting(cc_qti_tags
::rcardinality
, $value);
1569 public function enable_rtiming($value = true) {
1570 $this->enable_setting_yesno(cc_qti_tags
::rtiming
, $value);
1573 public function set_ident($value) {
1574 $this->set_setting(cc_qti_tags
::ident
, $value);
1577 public function get_ident() {
1578 return $this->get_setting(cc_qti_tags
::ident
);
1581 public function set_material_ref(cc_assesment_response_matref
$object) {
1582 $this->material_ref
= $object;
1585 public function set_material(cc_assesment_material
$object) {
1586 $this->material
= $object;
1589 public function set_render_choice(cc_assesment_render_choicetype
$object) {
1590 $this->render_choice
= $object;
1593 public function set_render_fib(cc_assesment_render_fibtype
$object) {
1594 $this->render_fib
= $object;
1597 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
1598 $node = $doc->append_new_element_ns($item, $namespace, $this->tagname
);
1599 $this->generate_attributes($doc, $node, $namespace);
1601 if (!empty($this->material
) && empty($this->material_ref
)) {
1602 $this->material
->generate($doc, $node, $namespace);
1605 if (!empty($this->material_ref
) && empty($this->material
)) {
1606 $this->material_ref
->generate($doc, $node, $namespace);
1609 if (!empty($this->render_choice
) && empty($this->render_fib
)) {
1610 $this->render_choice
->generate($doc, $node, $namespace);
1613 if (!empty($this->render_fib
) && empty($this->render_choice
)) {
1614 $this->render_fib
->generate($doc, $node, $namespace);
1619 class cc_assesment_response_strtype
extends cc_response_lidtype
{
1620 public function __construct() {
1621 $rtt = parent
::__construct();
1622 $this->tagname
= cc_qti_tags
::response_str
;
1626 class cc_assesment_flowtype
extends cc_question_metadata_base
{
1628 * @var cc_assesment_flowtype
1630 protected $flow = null;
1632 * @var cc_assesment_material
1634 protected $material = null;
1636 * @var cc_assesment_response_matref
1638 protected $material_ref = null;
1640 * @var cc_response_lidtype
1642 protected $response_lid = null;
1644 * @var cc_assesment_response_strtype
1646 protected $response_str = null;
1648 public function __construct() {
1649 $this->set_setting(cc_qti_tags
::t_class
);
1652 public function set_class($value) {
1653 $this->set_setting(cc_qti_tags
::t_class
, $value);
1656 public function set_flow(cc_assesment_flowtype
$object) {
1657 $this->flow
= $object;
1660 public function set_material(cc_assesment_material
$object) {
1661 $this->material
= $object;
1664 public function set_material_ref(cc_assesment_response_matref
$object) {
1665 $this->material_ref
= $object;
1668 public function set_response_lid(cc_response_lidtype
$object) {
1669 $this->response_lid
= $object;
1672 public function set_response_str(cc_assesment_response_strtype
$object) {
1673 $this->response_str
= $object;
1676 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
1677 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::flow
);
1678 $this->generate_attributes($doc, $node, $namespace);
1680 if (!empty($this->flow
)) {
1681 $this->flow
->generate($doc, $node, $namespace);
1684 if (!empty($this->material
)) {
1685 $this->material
->generate($doc, $node, $namespace);
1688 if (!empty($this->response_lid
)) {
1689 $this->response_lid
->generate($doc, $node, $namespace);
1692 if (!empty($this->response_str
)) {
1693 $this->response_str
->generate($doc, $node, $namespace);
1698 class cc_assesment_presentation
extends cc_question_metadata_base
{
1700 * @var cc_assesment_flowtype
1702 protected $flow = null;
1704 * @var cc_assesment_material
1706 protected $material = null;
1708 * @var cc_response_lidtype
1710 protected $response_lid = null;
1712 * @var cc_assesment_response_strtype
1714 protected $response_str = null;
1716 public function __construct() {
1717 $this->set_setting(cc_qti_tags
::label
);
1718 $this->set_setting_wns(cc_qti_tags
::xml_lang
, cc_xml_namespace
::xml
);
1719 $this->set_setting(cc_qti_tags
::x0
);
1720 $this->set_setting(cc_qti_tags
::y0
);
1721 $this->set_setting(cc_qti_tags
::width
);
1722 $this->set_setting(cc_qti_tags
::height
);
1725 public function set_label($value) {
1726 $this->set_setting(cc_qti_tags
::label
, $value);
1729 public function set_lang($value) {
1730 $this->set_setting_wns(cc_qti_tags
::xml_lang
, cc_xml_namespace
::xml
, $value);
1733 public function set_coor($x = null, $y = null) {
1734 $this->set_setting(cc_qti_tags
::x0
, $x);
1735 $this->set_setting(cc_qti_tags
::y0
, $y);
1738 public function set_size($width = null, $height = null) {
1739 $this->set_setting(cc_qti_tags
::width
, $width);
1740 $this->set_setting(cc_qti_tags
::height
, $height);
1743 public function set_flow(cc_assesment_flowtype
$object) {
1744 $this->flow
= $object;
1747 public function set_material(cc_assesment_material
$object) {
1748 $this->material
= $object;
1751 public function set_response_lid(cc_response_lidtype
$object) {
1752 $this->response_lid
= $object;
1755 public function set_response_str(cc_assesment_response_strtype
$object) {
1756 $this->response_str
= $object;
1759 public function generate(XMLGenericDocument
&$doc, DOMNode
&$item, $namespace) {
1760 $node = $doc->append_new_element_ns($item, $namespace, cc_qti_tags
::presentation
);
1761 $this->generate_attributes($doc, $node, $namespace);
1763 if (!empty($this->flow
)) {
1764 $this->flow
->generate($doc, $node, $namespace);
1767 if (!empty($this->material
) && empty($this->flow
)) {
1768 $this->material
->generate($doc, $node, $namespace);
1771 if (!empty($this->response_lid
) && empty($this->flow
)) {
1772 $this->response_lid
->generate($doc, $node, $namespace);
1775 if (!empty($this->response_str
) && empty($this->flow
)) {
1776 $this->response_str
->generate($doc, $node, $namespace);
1781 class assesment1_resurce_file
extends general_cc_file
{
1782 const deafultname
= 'assesment.xml';
1784 protected $rootns = 'xmlns';
1785 protected $rootname = cc_qti_tags
::questestinterop
;
1786 protected $ccnamespaces = array('xmlns' => 'http://www.imsglobal.org/xsd/ims_qtiasiv1p2',
1787 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance');
1788 protected $ccnsnames = array('xmlns' => 'http://www.imsglobal.org/profile/cc/ccv1p0/derived_schema/domainProfile_4/ims_qtiasiv1p2_localised.xsd');
1793 protected $assessment_title = 'Untitled';
1795 * @var cc_assesment_metadata
1797 protected $metadata = null;
1799 * @var cc_assesment_rubric_base
1801 protected $rubric = null;
1804 * @var cc_assesment_presentation_material_base
1806 protected $presentation_material = null;
1809 * @var cc_assesment_section
1811 protected $section = null;
1813 public function set_metadata(cc_assesment_metadata
$object) {
1814 $this->metadata
= $object;
1817 public function set_rubric(cc_assesment_rubric_base
$object) {
1818 $this->rubric
= $object;
1821 public function set_presentation_material(cc_assesment_presentation_material_base
$object) {
1822 $this->presentation_material
= $object;
1825 public function set_section(cc_assesment_section
$object) {
1826 $this->section
= $object;
1829 public function set_title($value) {
1830 $this->assessment_title
= self
::safexml($value);
1833 protected function on_save() {
1834 $rns = $this->ccnamespaces
[$this->rootns
];
1835 //root assesment element - required
1836 $assessment = $this->append_new_element_ns($this->root
, $rns, cc_qti_tags
::assessment
);
1837 $this->append_new_attribute_ns($assessment, $rns, cc_qti_tags
::ident
, cc_helpers
::uuidgen('QDB_'));
1838 $this->append_new_attribute_ns($assessment, $rns, cc_qti_tags
::title
, $this->assessment_title
);
1840 //metadata - optional
1841 if (!empty($this->metadata
)) {
1842 $this->metadata
->generate($this, $assessment, $rns);
1846 if (!empty($this->rubric
)) {
1847 $this->rubric
->generate($this, $assessment, $rns);
1850 //presentation_material - optional
1851 if (!empty($this->presentation_material
)) {
1852 $this->presentation_material
->generate($this, $assessment, $rns);
1855 //section - required
1856 if (!empty($this->section
)) {
1857 $this->section
->generate($this, $assessment, $rns);
1865 class assesment11_resurce_file
extends assesment1_resurce_file
{
1866 protected $ccnsnames = array('xmlns' => 'http://www.imsglobal.org/profile/cc/ccv1p1/ccv1p1_qtiasiv1p2p1_v1p0.xsd');
1869 abstract class cc_assesment_helper
{
1871 public static $correct_fb = null;
1872 public static $incorrect_fb = null;
1874 public static function add_feedback($qitem, $content, $content_type, $ident) {
1875 if (empty($content)) {
1878 $qitemfeedback = new cc_assesment_itemfeedbacktype();
1879 $qitem->add_itemfeedback($qitemfeedback);
1880 if (!empty($ident)) {
1881 $qitemfeedback->set_ident($ident);
1883 $qflowmat = new cc_assesment_flow_mattype();
1884 $qitemfeedback->set_flow_mat($qflowmat);
1885 $qmaterialfb = new cc_assesment_material();
1886 $qflowmat->set_material($qmaterialfb);
1887 $qmattext = new cc_assesment_mattext();
1888 $qmaterialfb->set_mattext($qmattext);
1889 $qmattext->set_content($content, $content_type);
1893 public static function add_answer($qresponse_choice, $content, $content_type) {
1894 $qresponse_label = new cc_assesment_response_labeltype();
1895 $qresponse_choice->add_response_label($qresponse_label);
1896 $qrespmaterial = new cc_assesment_material();
1897 $qresponse_label->set_material($qrespmaterial);
1898 $qrespmattext = new cc_assesment_mattext();
1899 $qrespmaterial->set_mattext($qrespmattext);
1900 $qrespmattext->set_content($content, $content_type);
1901 return $qresponse_label;
1904 public static function add_response_condition($node, $title, $ident, $feedback_refid, $respident) {
1905 $qrespcondition = new cc_assesment_respconditiontype();
1906 $node->add_respcondition($qrespcondition);
1907 //define rest of the conditions
1908 $qconditionvar = new cc_assignment_conditionvar();
1909 $qrespcondition->set_conditionvar($qconditionvar);
1910 $qvarequal = new cc_assignment_conditionvar_varequaltype($ident);
1911 $qvarequal->enable_case();
1912 $qconditionvar->set_varequal($qvarequal);
1913 $qvarequal->set_respident($respident);
1914 $qdisplayfeedback = new cc_assignment_displayfeedbacktype();
1915 $qrespcondition->add_displayfeedback($qdisplayfeedback);
1916 $qdisplayfeedback->set_feedbacktype(cc_qti_values
::Response
);
1917 $qdisplayfeedback->set_linkrefid($feedback_refid);
1920 public static function add_assesment_description($rt, $content, $contenttype) {
1921 if (empty($rt) ||
empty($content)) {
1924 $activity_rubric = new cc_assesment_rubric_base();
1925 $rubric_material = new cc_assesment_material();
1926 $activity_rubric->set_material($rubric_material);
1927 $rubric_mattext = new cc_assesment_mattext();
1928 $rubric_material->set_label('Summary');
1929 $rubric_material->set_mattext($rubric_mattext);
1930 $rubric_mattext->set_content($content, $contenttype);
1931 $rt->set_rubric($activity_rubric);
1934 public static function add_respcondition($node, $title, $feedback_refid, $grade_value = null, $continue = false ) {
1935 $qrespcondition = new cc_assesment_respconditiontype();
1936 $qrespcondition->set_title($title);
1937 $node->add_respcondition($qrespcondition);
1938 $qrespcondition->enable_continue($continue);
1939 //Add setvar if grade present
1940 if ($grade_value !== null) {
1941 $qsetvar = new cc_assignment_setvartype($grade_value);
1942 $qrespcondition->add_setvar($qsetvar);
1944 //define the condition for success
1945 $qconditionvar = new cc_assignment_conditionvar();
1946 $qrespcondition->set_conditionvar($qconditionvar);
1947 $qother = new cc_assignment_conditionvar_othertype();
1948 $qconditionvar->set_other($qother);
1949 $qdisplayfeedback = new cc_assignment_displayfeedbacktype();
1950 $qrespcondition->add_displayfeedback($qdisplayfeedback);
1951 $qdisplayfeedback->set_feedbacktype(cc_qti_values
::Response
);
1952 $qdisplayfeedback->set_linkrefid($feedback_refid);
1957 * Enter description here ...
1958 * @param XMLGenericDocument $qdoc
1959 * @param unknown_type $manifest
1960 * @param cc_assesment_section $section
1961 * @param unknown_type $rootpath
1962 * @param unknown_type $contextid
1963 * @param unknown_type $outdir
1965 public static function process_questions(&$qdoc, &$manifest, cc_assesment_section
&$section, $rootpath, $contextid, $outdir) {
1966 $question_file = $rootpath . DIRECTORY_SEPARATOR
. 'questions.xml';
1967 //load questions file
1968 $questions = new XMLGenericDocument();
1969 if (!$questions->load($question_file)) {
1973 pkg_resource_dependencies
::instance()->reset();
1975 $questionforexport = 0;
1976 $qids = $qdoc->nodeList('//question_instances//questionid');
1977 foreach ($qids as $qid) {
1978 /** @var DOMNode $qid */
1979 $value = $qid->nodeValue
;
1980 if (intval($value) == 0) {
1983 $question_node = $questions->node("//question_category/questions/question[@id='{$value}']");
1984 if (empty($question_node)) {
1987 ++
$questionforexport;
1990 $qtype = $questions->nodeValue('qtype', $question_node);
1991 $question_processor = null;
1994 $single_correct_answer = (int)$questions->nodeValue('plugin_qtype_multichoice_question/multichoice/single', $question_node) > 0;
1995 //TODO: Add checking for the nunmber of valid responses
1996 //If question is marked as multi response but contains only one valid answer it
1997 //should be handle as single response - classic multichoice
1998 if ($single_correct_answer) {
1999 $question_processor = new cc_assesment_question_multichoice($qdoc, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir);
2001 $question_processor = new cc_assesment_question_multichoice_multiresponse($qdoc, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir);
2003 $question_processor->generate();
2007 $question_processor = new cc_assesment_question_truefalse($qdoc, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir);
2008 $question_processor->generate();
2012 $question_processor = new cc_assesment_question_essay($qdoc, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir);
2013 $question_processor->generate();
2017 //This is rather ambiguos since shortanswer supports partial pattern match
2018 //In order to detect pattern match we need to scan for all the responses
2019 //if at least one of the responses uses wildcards it should be treated as
2020 //pattern match, otherwise it should be simple fill in the blank
2021 if (self
::has_matching_element($questions, $question_node)) {
2022 //$question_processor = new cc_assesment_question_patternmatch($qdoc, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir);
2023 $questionforexport--;
2025 $question_processor = new cc_assesment_question_sfib($qdoc, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir);
2027 if (!empty($question_processor)) {
2028 $question_processor->generate();
2039 //return dependencies
2040 return ($questioncount == 0) ||
($questioncount != $questionforexport)?
2041 false: pkg_resource_dependencies
::instance()->get_deps();
2046 * Checks if question has matching element
2047 * @param XMLGenericDocument $questions
2048 * @param object $question_node
2051 public static function has_matching_element(XMLGenericDocument
$questions, $question_node) {
2052 $answers = $questions->nodeList('plugin_qtype_shortanswer_question//answertext', $question_node);
2054 foreach ($answers as $answer) {
2055 $prepare = str_replace('\*', '\#', $answer->nodeValue
);
2056 $result = (strpos($prepare, '*') !== false);
2066 class cc_assesment_question_proc_base
{
2068 * @var XMLGenericDocument
2070 protected $quiz = null;
2073 * @var XMLGenericDocument
2075 protected $questions = null;
2080 protected $manifest = null;
2083 * @var cc_assesment_section
2085 protected $section = null;
2090 protected $question_node = null;
2095 protected $rootpath = null;
2100 protected $contextid = null;
2105 protected $outdir = null;
2110 protected $qtype = null;
2113 * @var cc_question_metadata
2115 protected $qmetadata = null;
2118 * @var cc_assesment_section_item
2120 protected $qitem = null;
2123 * @var cc_assesment_presentation
2125 protected $qpresentation = null;
2128 * @var cc_response_lidtype
2130 protected $qresponse_lid = null;
2132 protected $qresprocessing = null;
2134 protected $correct_grade_value = null;
2135 protected $correct_answer_node_id = null;
2136 protected $correct_answer_ident = null;
2138 protected $total_grade_value = null;
2140 protected $answerlist = null;
2142 protected $general_feedback = null;
2143 protected $correct_feedbacks = array();
2144 protected $incorrect_feedbacks = array();
2147 * @param XMLGenericDocument $questions
2148 * @param cc_manifest $manifest
2149 * @param cc_assesment_section $section
2150 * @param DOMElement $question_node
2151 * @param string $rootpath
2152 * @param string $contextid
2153 * @param string $outdir
2155 public function __construct(XMLGenericDocument
&$quiz, XMLGenericDocument
&$questions, cc_manifest
&$manifest, cc_assesment_section
&$section, &$question_node, $rootpath, $contextid, $outdir) {
2156 $this->quiz
= $quiz;
2157 $this->questions
= $questions;
2158 $this->manifest
= $manifest;
2159 $this->section
= $section;
2160 $this->question_node
= $question_node;
2161 $this->rootpath
= $rootpath;
2162 $this->contextid
= $contextid;
2163 $this->outdir
= $outdir;
2166 $qitem = new cc_assesment_section_item();
2167 $this->section
->add_item($qitem);
2168 $qitem->set_title($this->questions
->nodeValue('name', $this->question_node
));
2169 $this->qitem
= $qitem;
2172 public function on_generate_metadata() {
2173 if (empty($this->qmetadata
)) {
2174 $this->qmetadata
= new cc_question_metadata($this->qtype
);
2175 //Get weighting value
2176 $weighting_value = (int)$this->questions
->nodeValue('defaultmark', $this->question_node
);
2177 if ($weighting_value > 1) {
2178 $this->qmetadata
->set_weighting($weighting_value);
2181 $question_category = $this->questions
->nodeValue('../../name', $this->question_node
);
2182 if (!empty($question_category)) {
2183 $this->qmetadata
->set_category($question_category);
2185 $rts = new cc_assesment_itemmetadata();
2186 $rts->add_metadata($this->qmetadata
);
2187 $this->qitem
->set_itemmetadata($rts);
2191 public function on_generate_presentation() {
2192 if (empty($this->qpresentation
)) {
2193 $qpresentation = new cc_assesment_presentation();
2194 $this->qitem
->set_presentation($qpresentation);
2196 $qmaterial = new cc_assesment_material();
2197 $qmattext = new cc_assesment_mattext();
2198 $question_text = $this->questions
->nodeValue('questiontext', $this->question_node
);
2199 $result = cc_helpers
::process_linked_files( $question_text,
2204 $qmattext->set_content($result[0], cc_qti_values
::htmltype
);
2205 $qmaterial->set_mattext($qmattext);
2206 $qpresentation->set_material($qmaterial);
2207 $this->qpresentation
= $qpresentation;
2208 pkg_resource_dependencies
::instance()->add($result[1]);
2212 public function on_generate_answers() {}
2213 public function on_generate_feedbacks() {
2214 $general_question_feedback = $this->questions
->nodeValue('generalfeedback', $this->question_node
);
2215 if (empty($general_question_feedback)) {
2218 $name = 'general_fb';
2219 //Add question general feedback - the one that should be always displayed
2220 $result = cc_helpers
::process_linked_files( $general_question_feedback,
2226 cc_assesment_helper
::add_feedback($this->qitem
,
2228 cc_qti_values
::htmltype
,
2230 pkg_resource_dependencies
::instance()->add($result[1]);
2231 $this->general_feedback
= $name;
2234 public function on_generate_response_processing() {
2236 $qresprocessing = new cc_assesment_resprocessingtype();
2237 $this->qitem
->add_resprocessing($qresprocessing);
2238 $qdecvar = new cc_assesment_decvartype();
2239 $qresprocessing->set_decvar($qdecvar);
2240 //according to the Common Cartridge 1.1 Profile: Implementation document
2241 //this should always be set to 0, 100 in case of question type that is not essay
2242 $qdecvar->set_limits(0,100);
2243 $qdecvar->set_vartype(cc_qti_values
::Decimal
);
2245 $this->qresprocessing
= $qresprocessing;
2249 public function generate() {
2250 $this->on_generate_metadata();
2252 $this->on_generate_presentation();
2254 $this->on_generate_answers();
2256 $this->on_generate_feedbacks();
2258 $this->on_generate_response_processing();
2263 class cc_assesment_question_multichoice
extends cc_assesment_question_proc_base
{
2264 public function __construct($quiz, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir) {
2265 parent
::__construct($quiz, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir);
2266 $this->qtype
= cc_qti_profiletype
::multiple_choice
;
2270 * What is needed is a maximum grade value taken from the answer fraction
2271 * It is supposed to always be between 1 and 0 in decimal representation,
2272 * however that is not always the case so a change in test was needed
2273 * but since we support here one correct answer type
2274 * correct answer would always have to be 1
2276 $correct_answer_node = $this->questions
->node("plugin_qtype_multichoice_question/answers/answer[fraction > 0]", $this->question_node
);
2277 if (empty($correct_answer_node)) {
2278 throw new RuntimeException('No correct answer!');
2280 $this->correct_answer_node_id
= $this->questions
->nodeValue('@id', $correct_answer_node);
2281 $maximum_quiz_grade = (int)$this->quiz
->nodeValue('/activity/quiz/grade');
2282 $this->total_grade_value
= ($maximum_quiz_grade +
1).'.0000000';
2285 public function on_generate_answers() {
2286 //add responses holder
2287 $qresponse_lid = new cc_response_lidtype();
2288 $this->qresponse_lid
= $qresponse_lid;
2289 $this->qpresentation
->set_response_lid($qresponse_lid);
2290 $qresponse_choice = new cc_assesment_render_choicetype();
2291 $qresponse_lid->set_render_choice($qresponse_choice);
2292 //Mark that question has only one correct answer -
2293 //which applies for multiple choice and yes/no questions
2294 $qresponse_lid->set_rcardinality(cc_qti_values
::Single
);
2295 //are we to shuffle the responses?
2296 $shuffle_answers = (int)$this->quiz
->nodeValue('/activity/quiz/shuffleanswers') > 0;
2297 $qresponse_choice->enable_shuffle($shuffle_answers);
2298 $answerlist = array();
2299 $qa_responses = $this->questions
->nodeList('plugin_qtype_multichoice_question/answers/answer', $this->question_node
);
2300 foreach ($qa_responses as $node) {
2301 $answer_content = $this->questions
->nodeValue('answertext', $node);
2302 $id = ((int)$this->questions
->nodeValue('@id', $node) == $this->correct_answer_node_id
);
2303 $result = cc_helpers
::process_linked_files( $answer_content,
2308 $qresponse_label = cc_assesment_helper
::add_answer( $qresponse_choice,
2310 cc_qti_values
::htmltype
);
2311 pkg_resource_dependencies
::instance()->add($result[1]);
2312 $answer_ident = $qresponse_label->get_ident();
2313 $feedback_ident = $answer_ident.'_fb';
2314 if (empty($this->correct_answer_ident
) && $id) {
2315 $this->correct_answer_ident
= $answer_ident;
2317 //add answer specific feedbacks if not empty
2318 $content = $this->questions
->nodeValue('feedback', $node);
2319 if (!empty($content)) {
2320 $result = cc_helpers
::process_linked_files( $content,
2327 cc_assesment_helper
::add_feedback( $this->qitem
,
2329 cc_qti_values
::htmltype
,
2332 pkg_resource_dependencies
::instance()->add($result[1]);
2334 $answerlist[$answer_ident] = $feedback_ident;
2338 $this->answerlist
= $answerlist;
2342 public function on_generate_feedbacks() {
2343 parent
::on_generate_feedbacks();
2344 //Question combined feedbacks
2345 $correct_question_fb = $this->questions
->nodeValue('plugin_qtype_multichoice_question/multichoice/correctfeedback', $this->question_node
);
2346 $incorrect_question_fb = $this->questions
->nodeValue('plugin_qtype_multichoice_question/multichoice/incorrectfeedback', $this->question_node
);
2347 $proc = array('correct_fb' => $correct_question_fb, 'general_incorrect_fb' => $incorrect_question_fb);
2348 foreach ($proc as $ident => $content) {
2349 if (empty($content)) {
2352 $result = cc_helpers
::process_linked_files( $content,
2358 cc_assesment_helper
::add_feedback( $this->qitem
,
2360 cc_qti_values
::htmltype
,
2363 pkg_resource_dependencies
::instance()->add($result[1]);
2364 if ($ident == 'correct_fb') {
2365 $this->correct_feedbacks
[] = $ident;
2367 $this->incorrect_feedbacks
[] = $ident;
2373 public function on_generate_response_processing() {
2374 parent
::on_generate_response_processing();
2378 * General unconditional feedback must be added as a first respcondition
2379 * without any condition and just displayfeedback (if exists)
2381 if (!empty($this->general_feedback
)) {
2382 $qrespcondition = new cc_assesment_respconditiontype();
2383 $qrespcondition->set_title('General feedback');
2384 $this->qresprocessing
->add_respcondition($qrespcondition);
2385 $qrespcondition->enable_continue();
2386 //define the condition for success
2387 $qconditionvar = new cc_assignment_conditionvar();
2388 $qrespcondition->set_conditionvar($qconditionvar);
2389 $qother = new cc_assignment_conditionvar_othertype();
2390 $qconditionvar->set_other($qother);
2391 $qdisplayfeedback = new cc_assignment_displayfeedbacktype();
2392 $qrespcondition->add_displayfeedback($qdisplayfeedback);
2393 $qdisplayfeedback->set_feedbacktype(cc_qti_values
::Response
);
2394 $qdisplayfeedback->set_linkrefid('general_fb');
2399 * For all question types outside of the Essay question, scoring is done in a
2400 * single <respcondition> with a continue flag set to No. The outcome is always
2401 * a variable named SCORE which value must be set to 100 in case of correct answer.
2402 * Partial scores (not 0 or 100) are not supported.
2404 $qrespcondition = new cc_assesment_respconditiontype();
2405 $qrespcondition->set_title('Correct');
2406 $this->qresprocessing
->add_respcondition($qrespcondition);
2407 $qrespcondition->enable_continue(false);
2408 $qsetvar = new cc_assignment_setvartype(100);
2409 $qrespcondition->add_setvar($qsetvar);
2410 //define the condition for success
2411 $qconditionvar = new cc_assignment_conditionvar();
2412 $qrespcondition->set_conditionvar($qconditionvar);
2413 $qvarequal = new cc_assignment_conditionvar_varequaltype($this->correct_answer_ident
);
2414 $qconditionvar->set_varequal($qvarequal);
2415 $qvarequal->set_respident($this->qresponse_lid
->get_ident());
2417 if (array_key_exists($this->correct_answer_ident
, $this->answerlist
)) {
2418 $qdisplayfeedback = new cc_assignment_displayfeedbacktype();
2419 $qrespcondition->add_displayfeedback($qdisplayfeedback);
2420 $qdisplayfeedback->set_feedbacktype(cc_qti_values
::Response
);
2421 $qdisplayfeedback->set_linkrefid($this->answerlist
[$this->correct_answer_ident
]);
2424 foreach ($this->correct_feedbacks
as $ident) {
2425 $qdisplayfeedback = new cc_assignment_displayfeedbacktype();
2426 $qrespcondition->add_displayfeedback($qdisplayfeedback);
2427 $qdisplayfeedback->set_feedbacktype(cc_qti_values
::Response
);
2428 $qdisplayfeedback->set_linkrefid($ident);
2431 //rest of the conditions
2432 foreach ($this->answerlist
as $ident => $refid) {
2433 if ($ident == $this->correct_answer_ident
) {
2437 $qrespcondition = new cc_assesment_respconditiontype();
2438 $this->qresprocessing
->add_respcondition($qrespcondition);
2439 $qsetvar = new cc_assignment_setvartype(0);
2440 $qrespcondition->add_setvar($qsetvar);
2441 //define the condition for fail
2442 $qconditionvar = new cc_assignment_conditionvar();
2443 $qrespcondition->set_conditionvar($qconditionvar);
2444 $qvarequal = new cc_assignment_conditionvar_varequaltype($ident);
2445 $qconditionvar->set_varequal($qvarequal);
2446 $qvarequal->set_respident($this->qresponse_lid
->get_ident());
2448 $qdisplayfeedback = new cc_assignment_displayfeedbacktype();
2449 $qrespcondition->add_displayfeedback($qdisplayfeedback);
2450 $qdisplayfeedback->set_feedbacktype(cc_qti_values
::Response
);
2451 $qdisplayfeedback->set_linkrefid($refid);
2453 foreach ($this->incorrect_feedbacks
as $ident) {
2454 $qdisplayfeedback = new cc_assignment_displayfeedbacktype();
2455 $qrespcondition->add_displayfeedback($qdisplayfeedback);
2456 $qdisplayfeedback->set_feedbacktype(cc_qti_values
::Response
);
2457 $qdisplayfeedback->set_linkrefid($ident);
2463 class cc_assesment_question_multichoice_multiresponse
extends cc_assesment_question_proc_base
{
2467 protected $correct_answers = null;
2469 public function __construct($quiz, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir) {
2470 parent
::__construct($quiz, $questions, $manifest, $section, $question_node, $rootpath, $contextid, $outdir);
2471 $this->qtype
= cc_qti_profiletype
::multiple_response
;
2473 $correct_answer_nodes = $this->questions
->nodeList("plugin_qtype_multichoice_question/answers/answer[fraction > 0]", $this->question_node
);
2474 if ($correct_answer_nodes->length
== 0) {
2475 throw new RuntimeException('No correct answer!');
2477 $this->correct_answers
= $correct_answer_nodes;
2478 //$this->correct_answer_node_id = $this->questions->nodeValue('@id', $correct_answer_node);
2479 $maximum_quiz_grade = (int)$this->quiz
->nodeValue('/activity/quiz/grade');
2480 $this->total_grade_value
= ($maximum_quiz_grade +
1).'.0000000';
2483 public function on_generate_answers() {
2484 //add responses holder
2485 $qresponse_lid = new cc_response_lidtype();
2486 $this->qresponse_lid
= $qresponse_lid;
2487 $this->qpresentation
->set_response_lid($qresponse_lid);
2488 $qresponse_choice = new cc_assesment_render_choicetype();
2489 $qresponse_lid->set_render_choice($qresponse_choice);
2490 //Mark that question has more than one correct answer
2491 $qresponse_lid->set_rcardinality(cc_qti_values
::Multiple
);
2492 //are we to shuffle the responses?
2493 $shuffle_answers = (int)$this->quiz
->nodeValue('/activity/quiz/shuffleanswers') > 0;
2494 $qresponse_choice->enable_shuffle($shuffle_answers);
2495 $answerlist = array();
2496 $qa_responses = $this->questions
->nodeList('plugin_qtype_multichoice_question/answers/answer', $this->question_node
);
2497 foreach ($qa_responses as $node) {
2498 $answer_content = $this->questions
->nodeValue('answertext', $node);
2499 $answer_grade_fraction = (float)$this->questions
->nodeValue('fraction', $node);
2500 $result = cc_helpers
::process_linked_files( $answer_content,
2505 $qresponse_label = cc_assesment_helper
::add_answer( $qresponse_choice,
2507 cc_qti_values
::htmltype
);
2508 pkg_resource_dependencies
::instance()->add($result[1]);
2509 $answer_ident = $qresponse_label->get_ident();
2510 $feedback_ident = $answer_ident.'_fb';
2511 //add answer specific feedbacks if not empty
2512 $content = $this->questions
->nodeValue('feedback', $node);
2513 if (!empty($content)) {
2514 $result = cc_helpers
::process_linked_files( $content,
2521 cc_assesment_helper
::add_feedback( $this->qitem
,
2523 cc_qti_values
::htmltype
,
2526 pkg_resource_dependencies
::instance()->add($result[1]);
2529 $answerlist[$answer_ident] = array($feedback_ident, ($answer_grade_fraction > 0));
2532 $this->answerlist
= $answerlist;
2536 public function on_generate_feedbacks() {
2537 parent
::on_generate_feedbacks();
2538 //Question combined feedbacks
2539 $correct_question_fb = $this->questions
->nodeValue('plugin_qtype_multichoice_question/multichoice/correctfeedback', $this->question_node
);
2540 $incorrect_question_fb = $this->questions
->nodeValue('plugin_qtype_multichoice_question/multichoice/incorrectfeedback', $this->question_node
);
2541 if (empty($correct_question_fb)) {
2542 //Hardcode some text for now
2543 $correct_question_fb = 'Well done!';
2545 if (empty($incorrect_question_fb)) {
2546 //Hardcode some text for now
2547 $incorrect_question_fb = 'Better luck next time!';
2550 $proc = array('correct_fb' => $correct_question_fb, 'incorrect_fb' => $incorrect_question_fb);
2551 foreach ($proc as $ident => $content) {
2552 if (empty($content)) {
2555 $result = cc_helpers
::process_linked_files( $content,
2561 cc_assesment_helper
::add_feedback( $this->qitem
,
2563 cc_qti_values
::htmltype
,
2566 pkg_resource_dependencies
::instance()->add($result[1]);
2567 if ($ident == 'correct_fb') {
2568 $this->correct_feedbacks
[$ident] = $ident;
2570 $this->incorrect_feedbacks
[$ident] = $ident;
2576 public function on_generate_response_processing() {
2577 parent
::on_generate_response_processing();
2581 * General unconditional feedback must be added as a first respcondition
2582 * without any condition and just displayfeedback (if exists)
2584 cc_assesment_helper
::add_respcondition( $this->qresprocessing
,
2586 $this->general_feedback
,
2593 * For all question types outside of the Essay question, scoring is done in a
2594 * single <respcondition> with a continue flag set to No. The outcome is always
2595 * a variable named SCORE which value must be set to 100 in case of correct answer.
2596 * Partial scores (not 0 or 100) are not supported.
2598 $qrespcondition = new cc_assesment_respconditiontype();
2599 $qrespcondition->set_title('Correct');
2600 $this->qresprocessing
->add_respcondition($qrespcondition);
2601 $qrespcondition->enable_continue(false);
2602 $qsetvar = new cc_assignment_setvartype(100);
2603 $qrespcondition->add_setvar($qsetvar);
2604 //define the condition for success
2605 $qconditionvar = new cc_assignment_conditionvar();
2606 $qrespcondition->set_conditionvar($qconditionvar);
2607 //create root and condition
2608 $qandcondition = new cc_assignment_conditionvar_andtype();
2609 $qconditionvar->set_and($qandcondition);
2610 foreach ($this->answerlist
as $ident => $refid) {
2611 $qvarequal = new cc_assignment_conditionvar_varequaltype($ident);
2612 $qvarequal->enable_case();
2614 $qandcondition->set_varequal($qvarequal);
2616 $qandcondition->set_not($qvarequal);
2618 $qvarequal->set_respident($this->qresponse_lid
->get_ident());
2621 $qdisplayfeedback = new cc_assignment_displayfeedbacktype();
2622 $qrespcondition->add_displayfeedback($qdisplayfeedback);
2623 $qdisplayfeedback->set_feedbacktype(cc_qti_values
::Response
);
2624 //TODO: this needs to be fixed
2625 reset($this->correct_feedbacks
);
2626 $ident = key($this->correct_feedbacks
);
2627 $qdisplayfeedback->set_linkrefid($ident);
2630 //rest of the conditions
2631 foreach ($this->answerlist
as $ident => $refid) {
2632 cc_assesment_helper
::add_response_condition( $this->qresprocessing
,
2633 'Incorrect feedback',
2635 $this->general_feedback
,
2636 $this->qresponse_lid
->get_ident()
2640 //Final element for incorrect feedback
2641 reset($this->incorrect_feedbacks
);
2642 $ident = key($this->incorrect_feedbacks
);
2643 cc_assesment_helper
::add_respcondition( $this->qresprocessing
,
2644 'Incorrect feedback',