ILIAS  release_4-3 Revision
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.assClozeTestExport.php
Go to the documentation of this file.
1 <?php
2  /*
3  +----------------------------------------------------------------------------+
4  | ILIAS open source |
5  +----------------------------------------------------------------------------+
6  | Copyright (c) 1998-2001 ILIAS open source, University of Cologne |
7  | |
8  | This program is free software; you can redistribute it and/or |
9  | modify it under the terms of the GNU General Public License |
10  | as published by the Free Software Foundation; either version 2 |
11  | of the License, or (at your option) any later version. |
12  | |
13  | This program is distributed in the hope that it will be useful, |
14  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16  | GNU General Public License for more details. |
17  | |
18  | You should have received a copy of the GNU General Public License |
19  | along with this program; if not, write to the Free Software |
20  | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21  +----------------------------------------------------------------------------+
22 */
23 
24 include_once "./Modules/TestQuestionPool/classes/export/qti12/class.assQuestionExport.php";
25 
36 {
46  function toXML($a_include_header = true, $a_include_binary = true, $a_shuffle = false, $test_output = false, $force_image_references = false)
47  {
48  global $ilias;
49 
50  include_once "./Services/Math/classes/class.EvalMath.php";
51  $eval = new EvalMath();
52  $eval->suppress_errors = TRUE;
53  include_once("./Services/Xml/classes/class.ilXmlWriter.php");
54  $a_xml_writer = new ilXmlWriter;
55  // set xml header
56  $a_xml_writer->xmlHeader();
57  $a_xml_writer->xmlStartTag("questestinterop");
58  $attrs = array(
59  "ident" => "il_".IL_INST_ID."_qst_".$this->object->getId(),
60  "title" => $this->object->getTitle(),
61  "maxattempts" => $this->object->getNrOfTries()
62  );
63  $a_xml_writer->xmlStartTag("item", $attrs);
64  // add question description
65  $a_xml_writer->xmlElement("qticomment", NULL, $this->object->getComment());
66  // add estimated working time
67  $workingtime = $this->object->getEstimatedWorkingTime();
68  $duration = sprintf("P0Y0M0DT%dH%dM%dS", $workingtime["h"], $workingtime["m"], $workingtime["s"]);
69  $a_xml_writer->xmlElement("duration", NULL, $duration);
70  // add ILIAS specific metadata
71  $a_xml_writer->xmlStartTag("itemmetadata");
72  $a_xml_writer->xmlStartTag("qtimetadata");
73  $a_xml_writer->xmlStartTag("qtimetadatafield");
74  $a_xml_writer->xmlElement("fieldlabel", NULL, "ILIAS_VERSION");
75  $a_xml_writer->xmlElement("fieldentry", NULL, $ilias->getSetting("ilias_version"));
76  $a_xml_writer->xmlEndTag("qtimetadatafield");
77  $a_xml_writer->xmlStartTag("qtimetadatafield");
78  $a_xml_writer->xmlElement("fieldlabel", NULL, "QUESTIONTYPE");
79  $a_xml_writer->xmlElement("fieldentry", NULL, CLOZE_TEST_IDENTIFIER);
80  $a_xml_writer->xmlEndTag("qtimetadatafield");
81  $a_xml_writer->xmlStartTag("qtimetadatafield");
82  $a_xml_writer->xmlElement("fieldlabel", NULL, "AUTHOR");
83  $a_xml_writer->xmlElement("fieldentry", NULL, $this->object->getAuthor());
84  $a_xml_writer->xmlEndTag("qtimetadatafield");
85  $a_xml_writer->xmlStartTag("qtimetadatafield");
86  $a_xml_writer->xmlElement("fieldlabel", NULL, "textgaprating");
87  $a_xml_writer->xmlElement("fieldentry", NULL, $this->object->getTextgapRating());
88  $a_xml_writer->xmlEndTag("qtimetadatafield");
89  $a_xml_writer->xmlStartTag("qtimetadatafield");
90  $a_xml_writer->xmlElement("fieldlabel", NULL, "fixedTextLength");
91  $a_xml_writer->xmlElement("fieldentry", NULL, $this->object->getFixedTextLength());
92  $a_xml_writer->xmlEndTag("qtimetadatafield");
93  $a_xml_writer->xmlStartTag("qtimetadatafield");
94  $a_xml_writer->xmlElement("fieldlabel", NULL, "identicalScoring");
95  $a_xml_writer->xmlElement("fieldentry", NULL, $this->object->getIdenticalScoring());
96  $a_xml_writer->xmlEndTag("qtimetadatafield");
97  $a_xml_writer->xmlEndTag("qtimetadata");
98  $a_xml_writer->xmlEndTag("itemmetadata");
99 
100  // PART I: qti presentation
101  $attrs = array(
102  "label" => $this->object->getTitle()
103  );
104  $a_xml_writer->xmlStartTag("presentation", $attrs);
105  // add flow to presentation
106  $a_xml_writer->xmlStartTag("flow");
107  $text_parts = preg_split("/\[gap.*?\[\/gap\]/", $this->object->getClozeText());
108  // add material with question text to presentation
109  for ($i = 0; $i <= $this->object->getGapCount(); $i++)
110  {
111  // n-th text part
112  if ($i == 0)
113  {
114  $this->object->addQTIMaterial($a_xml_writer, $text_parts[$i]);
115  }
116  else
117  {
118  $this->object->addQTIMaterial($a_xml_writer, $text_parts[$i], TRUE, FALSE);
119  }
120 
121  if ($i < $this->object->getGapCount())
122  {
123  // add gap
124  $gap = $this->object->getGap($i);
125  switch ($gap->getType())
126  {
127  case CLOZE_SELECT:
128  // comboboxes
129  $attrs = array(
130  "ident" => "gap_$i",
131  "rcardinality" => "Single"
132  );
133  $a_xml_writer->xmlStartTag("response_str", $attrs);
134  $solution = $this->object->getSuggestedSolution($i);
135  if (count($solution))
136  {
137  if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $solution["internal_link"], $matches))
138  {
139  $attrs = array(
140  "label" => "suggested_solution"
141  );
142  $a_xml_writer->xmlStartTag("material", $attrs);
143  $intlink = "il_" . IL_INST_ID . "_" . $matches[2] . "_" . $matches[3];
144  if (strcmp($matches[1], "") != 0)
145  {
146  $intlink = $solution["internal_link"];
147  }
148  $a_xml_writer->xmlElement("mattext", NULL, $intlink);
149  $a_xml_writer->xmlEndTag("material");
150  }
151  }
152 
153  $attrs = array("shuffle" => ($gap->getShuffle() ? "Yes" : "No"));
154  $a_xml_writer->xmlStartTag("render_choice", $attrs);
155 
156  // add answers
157  foreach ($gap->getItems() as $answeritem)
158  {
159  $attrs = array(
160  "ident" => $answeritem->getOrder()
161  );
162  $a_xml_writer->xmlStartTag("response_label", $attrs);
163  $a_xml_writer->xmlStartTag("material");
164  $a_xml_writer->xmlElement("mattext", NULL, $answeritem->getAnswertext());
165  $a_xml_writer->xmlEndTag("material");
166  $a_xml_writer->xmlEndTag("response_label");
167  }
168  $a_xml_writer->xmlEndTag("render_choice");
169  $a_xml_writer->xmlEndTag("response_str");
170  break;
171  case CLOZE_TEXT:
172  // text fields
173  $attrs = array(
174  "ident" => "gap_$i",
175  "rcardinality" => "Single"
176  );
177  $a_xml_writer->xmlStartTag("response_str", $attrs);
178  $solution = $this->object->getSuggestedSolution($i);
179  if (count($solution))
180  {
181  if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $solution["internal_link"], $matches))
182  {
183  $attrs = array(
184  "label" => "suggested_solution"
185  );
186  $a_xml_writer->xmlStartTag("material", $attrs);
187  $intlink = "il_" . IL_INST_ID . "_" . $matches[2] . "_" . $matches[3];
188  if (strcmp($matches[1], "") != 0)
189  {
190  $intlink = $solution["internal_link"];
191  }
192  $a_xml_writer->xmlElement("mattext", NULL, $intlink);
193  $a_xml_writer->xmlEndTag("material");
194  }
195  }
196  $attrs = array(
197  "fibtype" => "String",
198  "prompt" => "Box",
199  "columns" => $gap->getMaxWidth()
200  );
201  $a_xml_writer->xmlStartTag("render_fib", $attrs);
202  $a_xml_writer->xmlEndTag("render_fib");
203  $a_xml_writer->xmlEndTag("response_str");
204  break;
205  case CLOZE_NUMERIC:
206  // numeric fields
207  $attrs = array(
208  "ident" => "gap_$i",
209  "numtype" => "Decimal",
210  "rcardinality" => "Single"
211  );
212  $a_xml_writer->xmlStartTag("response_num", $attrs);
213  $solution = $this->object->getSuggestedSolution($i);
214  if (count($solution))
215  {
216  if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $solution["internal_link"], $matches))
217  {
218  $attrs = array(
219  "label" => "suggested_solution"
220  );
221  $a_xml_writer->xmlStartTag("material", $attrs);
222  $intlink = "il_" . IL_INST_ID . "_" . $matches[2] . "_" . $matches[3];
223  if (strcmp($matches[1], "") != 0)
224  {
225  $intlink = $solution["internal_link"];
226  }
227  $a_xml_writer->xmlElement("mattext", NULL, $intlink);
228  $a_xml_writer->xmlEndTag("material");
229  }
230  }
231  $answeritem = $gap->getItem(0);
232  $attrs = array(
233  "fibtype" => "Decimal",
234  "prompt" => "Box",
235  "columns" => $gap->getMaxWidth()
236  );
237  if (is_object($answeritem))
238  {
239  if ($eval->e($answeritem->getLowerBound()) !== FALSE)
240  {
241  $attrs["minnumber"] = $answeritem->getLowerBound();
242  }
243  if ($eval->e($answeritem->getUpperBound()) !== FALSE)
244  {
245  $attrs["maxnumber"] = $answeritem->getUpperBound();
246  }
247  }
248  $a_xml_writer->xmlStartTag("render_fib", $attrs);
249  $a_xml_writer->xmlEndTag("render_fib");
250  $a_xml_writer->xmlEndTag("response_num");
251  break;
252  }
253  }
254  }
255  $a_xml_writer->xmlEndTag("flow");
256  $a_xml_writer->xmlEndTag("presentation");
257 
258  // PART II: qti resprocessing
259  $a_xml_writer->xmlStartTag("resprocessing");
260  $a_xml_writer->xmlStartTag("outcomes");
261  $a_xml_writer->xmlStartTag("decvar");
262  $a_xml_writer->xmlEndTag("decvar");
263  $a_xml_writer->xmlEndTag("outcomes");
264 
265  // add response conditions
266  for ($i = 0; $i < $this->object->getGapCount(); $i++)
267  {
268  $gap = $this->object->getGap($i);
269  switch ($gap->getType())
270  {
271  case CLOZE_SELECT:
272  foreach ($gap->getItems() as $answer)
273  {
274  $attrs = array(
275  "continue" => "Yes"
276  );
277  $a_xml_writer->xmlStartTag("respcondition", $attrs);
278  // qti conditionvar
279  $a_xml_writer->xmlStartTag("conditionvar");
280 
281  $attrs = array(
282  "respident" => "gap_$i"
283  );
284  $a_xml_writer->xmlElement("varequal", $attrs, $answer->getAnswertext());
285  $a_xml_writer->xmlEndTag("conditionvar");
286  // qti setvar
287  $attrs = array(
288  "action" => "Add"
289  );
290  $a_xml_writer->xmlElement("setvar", $attrs, $answer->getPoints());
291  // qti displayfeedback
292  $linkrefid = "";
293  $linkrefid = "$i" . "_Response_" . $answer->getOrder();
294  $attrs = array(
295  "feedbacktype" => "Response",
296  "linkrefid" => $linkrefid
297  );
298  $a_xml_writer->xmlElement("displayfeedback", $attrs);
299  $a_xml_writer->xmlEndTag("respcondition");
300  }
301  break;
302  case CLOZE_TEXT:
303  foreach ($gap->getItems() as $answer)
304  {
305  $attrs = array(
306  "continue" => "Yes"
307  );
308  $a_xml_writer->xmlStartTag("respcondition", $attrs);
309  // qti conditionvar
310  $a_xml_writer->xmlStartTag("conditionvar");
311  $attrs = array(
312  "respident" => "gap_$i"
313  );
314  $a_xml_writer->xmlElement("varequal", $attrs, $answer->getAnswertext());
315  $a_xml_writer->xmlEndTag("conditionvar");
316  // qti setvar
317  $attrs = array(
318  "action" => "Add"
319  );
320  $a_xml_writer->xmlElement("setvar", $attrs, $answer->getPoints());
321  // qti displayfeedback
322  $linkrefid = "$i" . "_Response_" . $answer->getOrder();
323  $attrs = array(
324  "feedbacktype" => "Response",
325  "linkrefid" => $linkrefid
326  );
327  $a_xml_writer->xmlElement("displayfeedback", $attrs);
328  $a_xml_writer->xmlEndTag("respcondition");
329  }
330  break;
331  case CLOZE_NUMERIC:
332  foreach ($gap->getItems() as $answer)
333  {
334  $attrs = array(
335  "continue" => "Yes"
336  );
337  $a_xml_writer->xmlStartTag("respcondition", $attrs);
338  // qti conditionvar
339  $a_xml_writer->xmlStartTag("conditionvar");
340  $attrs = array(
341  "respident" => "gap_$i"
342  );
343  $a_xml_writer->xmlElement("varequal", $attrs, $answer->getAnswertext());
344  $a_xml_writer->xmlEndTag("conditionvar");
345  // qti setvar
346  $attrs = array(
347  "action" => "Add"
348  );
349  $a_xml_writer->xmlElement("setvar", $attrs, $answer->getPoints());
350  // qti displayfeedback
351  $linkrefid = "$i" . "_Response_" . $answer->getOrder();
352  $attrs = array(
353  "feedbacktype" => "Response",
354  "linkrefid" => $linkrefid
355  );
356  $a_xml_writer->xmlElement("displayfeedback", $attrs);
357  $a_xml_writer->xmlEndTag("respcondition");
358  }
359  break;
360  }
361  }
362 
363  $feedback_allcorrect = $this->object->getFeedbackGeneric(1);
364  if (strlen($feedback_allcorrect))
365  {
366  $attrs = array(
367  "continue" => "Yes"
368  );
369  $a_xml_writer->xmlStartTag("respcondition", $attrs);
370  // qti conditionvar
371  $a_xml_writer->xmlStartTag("conditionvar");
372 
373  for ($i = 0; $i < $this->object->getGapCount(); $i++)
374  {
375  $gap = $this->object->getGap($i);
376  $indexes = $gap->getBestSolutionIndexes();
377  if ($i > 0)
378  {
379  $a_xml_writer->xmlStartTag("and");
380  }
381  switch ($gap->getType())
382  {
383  case CLOZE_SELECT:
384  $k = 0;
385  foreach ($indexes as $key)
386  {
387  if ($k > 0)
388  {
389  $a_xml_writer->xmlStartTag("or");
390  }
391  $attrs = array(
392  "respident" => "gap_$i"
393  );
394  $answer = $gap->getItem($key);
395  $a_xml_writer->xmlElement("varequal", $attrs, $answer->getAnswertext());
396  if ($k > 0)
397  {
398  $a_xml_writer->xmlEndTag("or");
399  }
400  $k++;
401  }
402  break;
403  case CLOZE_TEXT:
404  $k = 0;
405  foreach ($indexes as $key)
406  {
407  if ($k > 0)
408  {
409  $a_xml_writer->xmlStartTag("or");
410  }
411  $attrs = array(
412  "respident" => "gap_$i"
413  );
414  $answer = $gap->getItem($key);
415  $a_xml_writer->xmlElement("varequal", $attrs, $answer->getAnswertext());
416  if ($k > 0)
417  {
418  $a_xml_writer->xmlEndTag("or");
419  }
420  $k++;
421  }
422  break;
423  case CLOZE_NUMERIC:
424  $k = 0;
425  foreach ($indexes as $key)
426  {
427  if ($k > 0)
428  {
429  $a_xml_writer->xmlStartTag("or");
430  }
431  $attrs = array(
432  "respident" => "gap_$i"
433  );
434  $answer = $gap->getItem($key);
435  $a_xml_writer->xmlElement("varequal", $attrs, $answer->getAnswertext());
436  if ($k > 0)
437  {
438  $a_xml_writer->xmlEndTag("or");
439  }
440  $k++;
441  }
442  break;
443  }
444  if ($i > 0)
445  {
446  $a_xml_writer->xmlEndTag("and");
447  }
448  }
449  $a_xml_writer->xmlEndTag("conditionvar");
450  // qti displayfeedback
451  $attrs = array(
452  "feedbacktype" => "Response",
453  "linkrefid" => "response_allcorrect"
454  );
455  $a_xml_writer->xmlElement("displayfeedback", $attrs);
456  $a_xml_writer->xmlEndTag("respcondition");
457  }
458  $feedback_onenotcorrect = $this->object->getFeedbackGeneric(0);
459  if (strlen($feedback_onenotcorrect))
460  {
461  $attrs = array(
462  "continue" => "Yes"
463  );
464  $a_xml_writer->xmlStartTag("respcondition", $attrs);
465  // qti conditionvar
466  $a_xml_writer->xmlStartTag("conditionvar");
467 
468  $a_xml_writer->xmlStartTag("not");
469  for ($i = 0; $i < $this->object->getGapCount(); $i++)
470  {
471  $gap = $this->object->getGap($i);
472  $indexes = $gap->getBestSolutionIndexes();
473  if ($i > 0)
474  {
475  $a_xml_writer->xmlStartTag("and");
476  }
477  switch ($gap->getType())
478  {
479  case CLOZE_SELECT:
480  $k = 0;
481  foreach ($indexes as $key)
482  {
483  if ($k > 0)
484  {
485  $a_xml_writer->xmlStartTag("or");
486  }
487  $attrs = array(
488  "respident" => "gap_$i"
489  );
490  $answer = $gap->getItem($key);
491  $a_xml_writer->xmlElement("varequal", $attrs, $answer->getAnswertext());
492  if ($k > 0)
493  {
494  $a_xml_writer->xmlEndTag("or");
495  }
496  $k++;
497  }
498  break;
499  case CLOZE_TEXT:
500  $k = 0;
501  foreach ($indexes as $key)
502  {
503  if ($k > 0)
504  {
505  $a_xml_writer->xmlStartTag("or");
506  }
507  $attrs = array(
508  "respident" => "gap_$i"
509  );
510  $answer = $gap->getItem($key);
511  $a_xml_writer->xmlElement("varequal", $attrs, $answer->getAnswertext());
512  if ($k > 0)
513  {
514  $a_xml_writer->xmlEndTag("or");
515  }
516  $k++;
517  }
518  break;
519  case CLOZE_NUMERIC:
520  $k = 0;
521  foreach ($indexes as $key)
522  {
523  if ($k > 0)
524  {
525  $a_xml_writer->xmlStartTag("or");
526  }
527  $attrs = array(
528  "respident" => "gap_$i"
529  );
530  $answer = $gap->getItem($key);
531  $a_xml_writer->xmlElement("varequal", $attrs, $answer->getAnswertext());
532  if ($k > 0)
533  {
534  $a_xml_writer->xmlEndTag("or");
535  }
536  $k++;
537  }
538  break;
539  }
540  if ($i > 0)
541  {
542  $a_xml_writer->xmlEndTag("and");
543  }
544  }
545  $a_xml_writer->xmlEndTag("not");
546  $a_xml_writer->xmlEndTag("conditionvar");
547  // qti displayfeedback
548  $attrs = array(
549  "feedbacktype" => "Response",
550  "linkrefid" => "response_onenotcorrect"
551  );
552  $a_xml_writer->xmlElement("displayfeedback", $attrs);
553  $a_xml_writer->xmlEndTag("respcondition");
554  }
555 
556  $a_xml_writer->xmlEndTag("resprocessing");
557 
558  // PART III: qti itemfeedback
559  for ($i = 0; $i < $this->object->getGapCount(); $i++)
560  {
561  $gap = $this->object->getGap($i);
562  switch ($gap->getType())
563  {
564  case CLOZE_SELECT:
565  foreach ($gap->getItems() as $answer)
566  {
567  $linkrefid = "$i" . "_Response_" . $answer->getOrder();
568  $attrs = array(
569  "ident" => $linkrefid,
570  "view" => "All"
571  );
572  $a_xml_writer->xmlStartTag("itemfeedback", $attrs);
573  // qti flow_mat
574  $a_xml_writer->xmlStartTag("flow_mat");
575  $a_xml_writer->xmlStartTag("material");
576  $a_xml_writer->xmlElement("mattext");
577  $a_xml_writer->xmlEndTag("material");
578  $a_xml_writer->xmlEndTag("flow_mat");
579  $a_xml_writer->xmlEndTag("itemfeedback");
580  }
581  break;
582  case CLOZE_TEXT:
583  foreach ($gap->getItems() as $answer)
584  {
585  $linkrefid = "$i" . "_Response_" . $answer->getOrder();
586  $attrs = array(
587  "ident" => $linkrefid,
588  "view" => "All"
589  );
590  $a_xml_writer->xmlStartTag("itemfeedback", $attrs);
591  // qti flow_mat
592  $a_xml_writer->xmlStartTag("flow_mat");
593  $a_xml_writer->xmlStartTag("material");
594  $a_xml_writer->xmlElement("mattext");
595  $a_xml_writer->xmlEndTag("material");
596  $a_xml_writer->xmlEndTag("flow_mat");
597  $a_xml_writer->xmlEndTag("itemfeedback");
598  }
599  break;
600  case CLOZE_NUMERIC:
601  foreach ($gap->getItems() as $answer)
602  {
603  $linkrefid = "$i" . "_Response_" . $answer->getOrder();
604  $attrs = array(
605  "ident" => $linkrefid,
606  "view" => "All"
607  );
608  $a_xml_writer->xmlStartTag("itemfeedback", $attrs);
609  // qti flow_mat
610  $a_xml_writer->xmlStartTag("flow_mat");
611  $a_xml_writer->xmlStartTag("material");
612  $a_xml_writer->xmlElement("mattext");
613  $a_xml_writer->xmlEndTag("material");
614  $a_xml_writer->xmlEndTag("flow_mat");
615  $a_xml_writer->xmlEndTag("itemfeedback");
616  }
617  break;
618  }
619  }
620 
621  if (strlen($feedback_allcorrect))
622  {
623  $attrs = array(
624  "ident" => "response_allcorrect",
625  "view" => "All"
626  );
627  $a_xml_writer->xmlStartTag("itemfeedback", $attrs);
628  // qti flow_mat
629  $a_xml_writer->xmlStartTag("flow_mat");
630  $this->object->addQTIMaterial($a_xml_writer, $feedback_allcorrect);
631  $a_xml_writer->xmlEndTag("flow_mat");
632  $a_xml_writer->xmlEndTag("itemfeedback");
633  }
634  if (strlen($feedback_onenotcorrect))
635  {
636  $attrs = array(
637  "ident" => "response_onenotcorrect",
638  "view" => "All"
639  );
640  $a_xml_writer->xmlStartTag("itemfeedback", $attrs);
641  // qti flow_mat
642  $a_xml_writer->xmlStartTag("flow_mat");
643  $this->object->addQTIMaterial($a_xml_writer, $feedback_onenotcorrect);
644  $a_xml_writer->xmlEndTag("flow_mat");
645  $a_xml_writer->xmlEndTag("itemfeedback");
646  }
647 
648  $a_xml_writer->xmlEndTag("item");
649  $a_xml_writer->xmlEndTag("questestinterop");
650 
651  $xml = $a_xml_writer->xmlDumpMem(FALSE);
652  if (!$a_include_header)
653  {
654  $pos = strpos($xml, "?>");
655  $xml = substr($xml, $pos + 2);
656  }
657  return $xml;
658  }
659 }
660 
661 ?>