• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

assessment/classes/class.assClozeTest.php

Go to the documentation of this file.
00001 <?php
00002  /*
00003    +----------------------------------------------------------------------------+
00004    | ILIAS open source                                                          |
00005    +----------------------------------------------------------------------------+
00006    | Copyright (c) 1998-2001 ILIAS open source, University of Cologne           |
00007    |                                                                            |
00008    | This program is free software; you can redistribute it and/or              |
00009    | modify it under the terms of the GNU General Public License                |
00010    | as published by the Free Software Foundation; either version 2             |
00011    | of the License, or (at your option) any later version.                     |
00012    |                                                                            |
00013    | This program is distributed in the hope that it will be useful,            |
00014    | but WITHOUT ANY WARRANTY; without even the implied warranty of             |
00015    | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              |
00016    | GNU General Public License for more details.                               |
00017    |                                                                            |
00018    | You should have received a copy of the GNU General Public License          |
00019    | along with this program; if not, write to the Free Software                |
00020    | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
00021    +----------------------------------------------------------------------------+
00022 */
00023 
00024 require_once "./assessment/classes/class.assQuestion.php";
00025 require_once "./assessment/classes/class.assAnswerCloze.php";
00026 require_once "./assessment/classes/class.ilQTIUtils.php";
00027 
00028 define("CLOZE_TEXT", "0");
00029 define("CLOZE_SELECT", "1");
00030 define("CLOZE_TEST_IDENTIFIER", "CLOZE QUESTION");
00031 
00042 class ASS_ClozeTest extends ASS_Question
00043 {
00052         var $cloze_text;
00053 
00061         var $gaps;
00062 
00070         var $start_tag;
00071 
00079         var $end_tag;
00092         function ASS_ClozeTest(
00093                 $title = "",
00094                 $comment = "",
00095                 $author = "",
00096                 $owner = -1,
00097                 $cloze_text = ""
00098         )
00099         {
00100                 $this->start_tag = "<gap>";
00101                 $this->end_tag = "</gap>";
00102                 $this->ASS_Question($title, $comment, $author, $owner);
00103                 $this->gaps = array();
00104                 $this->set_cloze_text($cloze_text);
00105         }
00106 
00115         function isComplete()
00116         {
00117                 if (($this->title) and ($this->author) and ($this->cloze_text) and (count($this->gaps)))
00118                 {
00119                         return true;
00120                 }
00121                 else
00122                 {
00123                         return false;
00124                 }
00125         }
00126 
00135         function &createCloseTextArray()
00136         {
00137                 $result = array();
00138                 $search_pattern = "|<gap([^>]*?)>(.*?)</gap>|i";
00139                 preg_match_all($search_pattern, $this->cloze_text, $gaps);
00140                 if (count($gaps[0]))
00141                 {
00142                         // found at least one gap
00143                         $delimiters = preg_split($search_pattern, $this->cloze_text, -1, PREG_SPLIT_OFFSET_CAPTURE);
00144                         $result["gaps"] = array();
00145                         foreach ($gaps[0] as $index => $gap)
00146                         {
00147                                 $result["gaps"][$index] = array();
00148                                 $result["gaps"][$index]["gap"] = $gap;
00149                                 $result["gaps"][$index]["params"] = array();
00150                                 $result["gaps"][$index]["params"]["text"] = $gaps[1][$index];
00151                                 // separate gap params
00152                                 if (preg_match("/name\=\"([^\"]*?)\"/", $gaps[1][$index], $params))
00153                                 {
00154                                         $result["gaps"][$index]["params"]["name"] = $params[1];
00155                                 }
00156                                 else
00157                                 {
00158                                         $result["gaps"][$index]["params"]["name"] = $this->lng->txt("gap") . " " . ($index+1);
00159                                 }
00160                                 if (preg_match("/type\=\"([^\"]*?)\"/", $gaps[1][$index], $params))
00161                                 {
00162                                         $result["gaps"][$index]["params"]["type"] = $params[1];
00163                                 }
00164                                 else
00165                                 {
00166                                         $result["gaps"][$index]["params"]["type"] = "text";
00167                                 }
00168                                 if (preg_match("/shuffle\=\"([^\"]*?)\"/", $gaps[1][$index], $params))
00169                                 {
00170                                         $result["gaps"][$index]["params"]["shuffle"] = $params[1];
00171                                 }
00172                                 else
00173                                 {
00174                                         if (strcmp(strtolower($result["gaps"][$index]["params"]["type"]), "select") == 0)
00175                                         {
00176                                                 $result["gaps"][$index]["params"]["shuffle"] = "yes";
00177                                         }
00178                                 }
00179                                 $result["gaps"][$index]["text"] = array();
00180                                 $result["gaps"][$index]["text"]["text"] = $gaps[2][$index];
00181                                 $textparams = preg_split("/(?<!\\\\),/", $gaps[2][$index]);
00182                                 foreach ($textparams as $key => $value)
00183                                 {
00184                                         $result["gaps"][$index]["text"][$key] = $value;
00185                                 }
00186                         }
00187                         $result["delimiters"] = $delimiters;
00188                 }
00189                 else
00190                 {
00191                         $result["gaps"] = array();
00192                         $result["delimiters"] = 
00193                                 array(
00194                                         array(0 => $this->cloze_text, 1 => "0")
00195                                 );
00196                 }
00197                 //echo str_replace("\n", "<br />", str_replace(" ", "&nbsp;", ilUtil::prepareFormOutput(print_r($result, true))));
00198                 return $result;         
00199         }
00200 
00209         function createCloseTextFromArray($assoc_array)
00210         {
00211                 $this->cloze_text = "";
00212                 if (count($assoc_array))
00213                 {
00214                         $gap = 0;
00215                         foreach ($assoc_array["delimiters"] as $key => $value)
00216                         {
00217                                 if (($key > 0) && ($key < count($assoc_array["delimiters"])))
00218                                 {
00219                                         if (strcmp($assoc_array["gaps"][$gap]["params"]["shuffle"], "") == 0)
00220                                         {
00221                                                 $shuffle = "";
00222                                         }
00223                                         else
00224                                         {
00225                                                 $shuffle = " shuffle=\"" . $assoc_array["gaps"][$gap]["params"]["shuffle"] . "\"";
00226                                         }
00227                                         $textarray = array();
00228                                         foreach ($assoc_array["gaps"][$gap]["text"] as $textindex => $textvalue)
00229                                         {
00230                                                 if (preg_match("/\d+/", $textindex))
00231                                                 {
00232                                                         array_push($textarray, $textvalue);
00233                                                 }
00234                                         }
00235                                         $this->cloze_text .= sprintf("<gap name=\"%s\" type=\"%s\"%s>%s</gap>",
00236                                                 $assoc_array["gaps"][$gap]["params"]["name"],
00237                                                 $assoc_array["gaps"][$gap]["params"]["type"],
00238                                                 $shuffle,
00239                                                 join(",", $textarray)
00240                                         );
00241                                         $gap++;
00242                                 }
00243                                 $this->cloze_text .= $value[0];
00244                         }
00245                 }
00246         }
00247         
00256         function saveToDb($original_id = "")
00257         {
00258                 global $ilias;
00259 
00260                 $db =& $ilias->db;
00261                 $complete = 0;
00262                 if ($this->isComplete())
00263                 {
00264                         $complete = 1;
00265                 }
00266 
00267                 $estw_time = $this->getEstimatedWorkingTime();
00268                 $estw_time = sprintf("%02d:%02d:%02d", $estw_time['h'], $estw_time['m'], $estw_time['s']);
00269                 $shuffle = 1;
00270 
00271                 if (!$this->shuffle)
00272                 {
00273                         $shuffle = 0;
00274                 }
00275 
00276                 if ($original_id)
00277                 {
00278                         $original_id = $db->quote($original_id);
00279                 }
00280                 else
00281                 {
00282                         $original_id = "NULL";
00283                 }
00284 
00285                 if ($this->id == -1)
00286                 {
00287                         // Neuen Datensatz schreiben
00288                         $now = getdate();
00289                         $created = sprintf("%04d%02d%02d%02d%02d%02d", $now['year'], $now['mon'], $now['mday'], $now['hours'], $now['minutes'], $now['seconds']);
00290                         $query = sprintf("INSERT INTO qpl_questions (question_id, question_type_fi, obj_fi, title, comment, points, author, owner, question_text, working_time, shuffle, complete, created, original_id, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
00291                                 $db->quote($this->getQuestionType()),
00292                                 $db->quote($this->obj_id),
00293                                 $db->quote($this->title),
00294                                 $db->quote($this->comment),
00295                                 $db->quote($this->getMaximumPoints() . ""),
00296                                 $db->quote($this->author),
00297                                 $db->quote($this->owner),
00298                                 $db->quote($this->cloze_text),
00299                                 $db->quote($estw_time),
00300                                 $db->quote("$this->shuffle"),
00301                                 $db->quote("$complete"),
00302                                 $db->quote($created),
00303                                 $original_id
00304                         );
00305                         $result = $db->query($query);
00306                         if ($result == DB_OK)
00307                         {
00308                                 $this->id = $this->ilias->db->getLastInsertId();
00309 
00310                                 // create page object of question
00311                                 $this->createPageObject();
00312 
00313                                 // Falls die Frage in einen Test eingef�gt werden soll, auch diese Verbindung erstellen
00314                                 if ($this->getTestId() > 0)
00315                                 {
00316                                         $this->insertIntoTest($this->getTestId());
00317                                 }
00318                         }
00319                 }
00320                 else
00321                 {
00322                         // Vorhandenen Datensatz aktualisieren
00323                         $query = sprintf("UPDATE qpl_questions SET obj_fi = %s, title = %s, comment = %s, points = %s, author = %s, question_text = %s, working_time = %s, shuffle = %s, complete = %s WHERE question_id = %s",
00324                                 $db->quote($this->obj_id. ""),
00325                                 $db->quote($this->title),
00326                                 $db->quote($this->comment),
00327                                 $db->quote($this->getMaximumPoints() . ""),
00328                                 $db->quote($this->author),
00329                                 $db->quote($this->cloze_text),
00330                                 $db->quote($estw_time),
00331                                 $db->quote("$this->shuffle"),
00332                                 $db->quote("$complete"),
00333                                 $db->quote($this->id)
00334                                 );
00335                         $result = $db->query($query);
00336                 }
00337 
00338                 if ($result == DB_OK)
00339                 {
00340                         // Antworten schreiben
00341 
00342                         // delete old answers
00343                         $query = sprintf("DELETE FROM qpl_answers WHERE question_fi = %s",
00344                                 $db->quote($this->id)
00345                         );
00346                         $result = $db->query($query);
00347                         // Anworten wegschreiben
00348                         foreach ($this->gaps as $key => $value)
00349                         {
00350                                 foreach ($value as $answer_id => $answer_obj)
00351                                 {
00352                                         $query = sprintf("INSERT INTO qpl_answers (answer_id, question_fi, gap_id, answertext, points, aorder, cloze_type, name, shuffle, correctness, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
00353                                                 $db->quote($this->id),
00354                                                 $db->quote($key),
00355                                                 $db->quote($answer_obj->get_answertext() . ""),
00356                                                 $db->quote($answer_obj->get_points() . ""),
00357                                                 $db->quote($answer_obj->get_order() . ""),
00358                                                 $db->quote($answer_obj->get_cloze_type() . ""),
00359                                                 $db->quote($answer_obj->get_name() . ""),
00360                                                 $db->quote($answer_obj->get_shuffle() . ""),
00361                                                 $db->quote($answer_obj->getState() . "")
00362                                                 );
00363                                         $answer_result = $db->query($query);
00364                                 }
00365                         }
00366                 }
00367                 parent::saveToDb($original_id);
00368         }
00369 
00379   function loadFromDb($question_id)
00380   {
00381     global $ilias;
00382     $db =& $ilias->db;
00383 
00384     $query = sprintf("SELECT * FROM qpl_questions WHERE question_id = %s",
00385       $db->quote($question_id)
00386     );
00387     $result = $db->query($query);
00388     if (strcmp(strtolower(get_class($result)), db_result) == 0) {
00389       if ($result->numRows() == 1) {
00390         $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
00391         $this->id = $question_id;
00392         $this->obj_id = $data->obj_fi;
00393         $this->title = $data->title;
00394         $this->comment = $data->comment;
00395                                 $this->solution_hint = $data->solution_hint;
00396                                 $this->original_id = $data->original_id;
00397         $this->author = $data->author;
00398                                 $this->points = $data->points;
00399         $this->owner = $data->owner;
00400         $this->cloze_text = $data->question_text;
00401                                 $this->shuffle = $data->shuffle;
00402         $this->setEstimatedWorkingTime(substr($data->working_time, 0, 2), substr($data->working_time, 3, 2), substr($data->working_time, 6, 2));
00403       }
00404 
00405       $query = sprintf("SELECT * FROM qpl_answers WHERE question_fi = %s ORDER BY gap_id, aorder ASC",
00406         $db->quote($question_id)
00407       );
00408       $result = $db->query($query);
00409       if (strcmp(strtolower(get_class($result)), db_result) == 0) {
00410         $counter = -1;
00411         while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
00412           if ($data->gap_id != $counter) {
00413             $answer_array = array();
00414             array_push($this->gaps, $answer_array);
00415             $counter = $data->gap_id;
00416           }
00417                                         if ($data->cloze_type == CLOZE_SELECT)
00418                                         {
00419                                                 if ($data->correctness == 0)
00420                                                 {
00421                                                         // fix for older single response answers where points could be given for unchecked answers
00422                                                         $data->correctness = 1;
00423                                                         $data->points = 0;
00424                                                 }
00425                                         }
00426           array_push($this->gaps[$counter], new ASS_AnswerCloze($data->answertext, $data->points, $data->aorder, $data->correctness, $data->cloze_type, $data->name, $data->shuffle, $data->answer_id));
00427         }
00428       }
00429     }
00430                 parent::loadFromDb($question_id);
00431   }
00432         
00440         function addAnswer($gap, $answertext, $points, $answerorder, $correctness, $clozetype, $name, $shuffle, $answer_id = -1)
00441         {
00442                 if (!is_array($this->gaps[$gap]))
00443                 {
00444                         $this->gaps[$gap] = array();
00445                 }
00446                 array_push($this->gaps[$gap], new ASS_AnswerCloze($answertext, $points, $answerorder, $correctness, $clozetype, $name, $shuffle, $answer_id));
00447         }
00448         
00456         function duplicate($for_test = true, $title = "", $author = "", $owner = "")
00457         {
00458                 if ($this->id <= 0)
00459                 {
00460                         // The question has not been saved. It cannot be duplicated
00461                         return;
00462                 }
00463                 // duplicate the question in database
00464                 $clone = $this;
00465                 include_once ("./assessment/classes/class.assQuestion.php");
00466                 $original_id = ASS_Question::_getOriginalId($this->id);
00467                 $clone->id = -1;
00468                 if ($title)
00469                 {
00470                         $clone->setTitle($title);
00471                 }
00472                 if ($author)
00473                 {
00474                         $clone->setAuthor($author);
00475                 }
00476                 if ($owner)
00477                 {
00478                         $clone->setOwner($owner);
00479                 }
00480                 if ($for_test)
00481                 {
00482                         $clone->saveToDb($original_id);
00483                 }
00484                 else
00485                 {
00486                         $clone->saveToDb();
00487                 }
00488 
00489                 // copy question page content
00490                 $clone->copyPageOfQuestion($original_id);
00491 
00492                 return $clone->id;
00493         }
00494         
00504         function from_xml($xml_text)
00505         {
00506                 $result = false;
00507                 if (!empty($this->domxml))
00508                 {
00509                         $this->domxml->free();
00510                 }
00511                 $xml_text = preg_replace("/>\s*?</", "><", $xml_text);
00512                 $this->domxml = domxml_open_mem($xml_text);
00513                 if (!empty($this->domxml))
00514                 {
00515                         $root = $this->domxml->document_element();
00516                         $item = $root->first_child();
00517                         $this->setTitle($item->get_attribute("title"));
00518                         $this->gaps = array();
00519                         $itemnodes = $item->child_nodes();
00520                         $materials = array();
00521                         $gapcounter = 0;
00522                         foreach ($itemnodes as $index => $node)
00523                         {
00524                                 switch ($node->node_name())
00525                                 {
00526                                         case "qticomment":
00527                                                 $comment = $node->get_content();
00528                                                 if (strpos($comment, "ILIAS Version=") !== false)
00529                                                 {
00530                                                 }
00531                                                 elseif (strpos($comment, "Questiontype=") !== false)
00532                                                 {
00533                                                 }
00534                                                 elseif (strpos($comment, "Author=") !== false)
00535                                                 {
00536                                                         $comment = str_replace("Author=", "", $comment);
00537                                                         $this->setAuthor($comment);
00538                                                 }
00539                                                 else
00540                                                 {
00541                                                         $this->setComment($comment);
00542                                                 }
00543                                                 break;
00544                                         case "itemmetadata":
00545                                                 $md_array = array();
00546                                                 $metanodes = $node->child_nodes();
00547                                                 foreach ($metanodes as $metanode)
00548                                                 {
00549                                                         switch ($metanode->node_name())
00550                                                         {
00551                                                                 case "qtimetadata":
00552                                                                         $metafields = $metanode->child_nodes();
00553                                                                         foreach ($metafields as $metafield)
00554                                                                         {
00555                                                                                 switch ($metafield->node_name())
00556                                                                                 {
00557                                                                                         case "qtimetadatafield":
00558                                                                                                 $metafieldlist = $metafield->child_nodes();
00559                                                                                                 $md = array("label" => "", "entry" => "");
00560                                                                                                 foreach ($metafieldlist as $attr)
00561                                                                                                 {
00562                                                                                                         switch ($attr->node_name())
00563                                                                                                         {
00564                                                                                                                 case "fieldlabel":
00565                                                                                                                         $md["label"] = $attr->get_content();
00566                                                                                                                         break;
00567                                                                                                                 case "fieldentry":
00568                                                                                                                         $md["entry"] = $attr->get_content();
00569                                                                                                                         break;
00570                                                                                                         }
00571                                                                                                 }
00572                                                                                                 array_push($md_array, $md);
00573                                                                                                 break;
00574                                                                                 }
00575                                                                         }
00576                                                                         break;
00577                                                         }
00578                                                 }
00579                                                 foreach ($md_array as $md)
00580                                                 {
00581                                                         switch ($md["label"])
00582                                                         {
00583                                                                 case "ILIAS_VERSION":
00584                                                                         break;
00585                                                                 case "QUESTIONTYPE":
00586                                                                         break;
00587                                                                 case "AUTHOR":
00588                                                                         $this->setAuthor($md["entry"]);
00589                                                                         break;
00590                                                         }
00591                                                 }
00592                                                 break;
00593                                         case "duration":
00594                                                 $iso8601period = $node->get_content();
00595                                                 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
00596                                                 {
00597                                                         $this->setEstimatedWorkingTime($matches[4], $matches[5], $matches[6]);
00598                                                 }
00599                                                 break;
00600                                         case "presentation":
00601                                                 $flow = $node->first_child();
00602                                                 $flownodes = $flow->child_nodes();
00603                                                 foreach ($flownodes as $idx => $flownode)
00604                                                 {
00605                                                         if (strcmp($flownode->node_name(), "material") == 0)
00606                                                         {
00607                                                                 $mattext = $flownode->first_child();
00608                                                                 array_push($materials, $mattext->get_content());
00609                                                         }
00610                                                         elseif (strcmp($flownode->node_name(), "response_str") == 0)
00611                                                         {
00612                                                                 $ident = $flownode->get_attribute("ident");
00613                                                                 $this->gaps["$ident"] = array();
00614                                                                 $shuffle = "";
00615                                                                 $subnodes = $flownode->child_nodes();
00616                                                                 foreach ($subnodes as $node_type)
00617                                                                 {
00618                                                                         switch ($node_type->node_name())
00619                                                                         {
00620                                                                                 case "render_choice":
00621                                                                                         $render_type = $node_type;
00622                                                                                         if (strcmp($render_type->node_name(), "render_choice") == 0)
00623                                                                                         {
00624                                                                                                 // select gap
00625                                                                                                 $shuffle = $render_type->get_attribute("shuffle");
00626                                                                                                 $labels = $render_type->child_nodes();
00627                                                                                                 foreach ($labels as $lidx => $response_label)
00628                                                                                                 {
00629                                                                                                         $material = $response_label->first_child();
00630                                                                                                         $mattext = $material->first_child();
00631                                                                                                         $shuf = 0;
00632                                                                                                         if (strcmp(strtolower($shuffle), "yes") == 0)
00633                                                                                                         {
00634                                                                                                                 $shuf = 1;
00635                                                                                                         }
00636                                                                                                         array_push($this->gaps["$ident"], new ASS_AnswerCloze($mattext->get_content(), 0, count($this->gaps["$ident"]), 0, CLOZE_SELECT, $ident, $shuf));
00637                                                                                                 }
00638                                                                                         }
00639                                                                                         break;
00640                                                                                 case "render_fib":
00641                                                                                         break;
00642                                                                                 case "material":
00643                                                                                         $matlabel = $node_type->get_attribute("label");
00644                                                                                         if (strcmp($matlabel, "suggested_solution") == 0)
00645                                                                                         {
00646                                                                                                 $mattype = $node_type->first_child();
00647                                                                                                 if (strcmp($mattype->node_name(), "mattext") == 0)
00648                                                                                                 {
00649                                                                                                         $suggested_solution = $mattype->get_content();
00650                                                                                                         if ($suggested_solution)
00651                                                                                                         {
00652                                                                                                                 if ($this->getId() < 1)
00653                                                                                                                 {
00654                                                                                                                         $this->saveToDb();
00655                                                                                                                 }
00656                                                                                                                 if (preg_match("/gap_(\d+)/", $ident, $matches))
00657                                                                                                                 {
00658                                                                                                                         $this->setSuggestedSolution($suggested_solution, $matches[1], true);
00659                                                                                                                 }
00660                                                                                                         }
00661                                                                                                 }
00662                                                                                         }
00663                                                                                         break;
00664                                                                         }
00665                                                                 }
00666                                                         }
00667                                                 }
00668                                                 break;
00669                                         case "resprocessing":
00670                                                 $resproc_nodes = $node->child_nodes();
00671                                                 foreach ($resproc_nodes as $index => $respcondition)
00672                                                 {
00673                                                         if (strcmp($respcondition->node_name(), "respcondition") == 0)
00674                                                         {
00675                                                                 $respcondition_array =& ilQTIUtils::_getRespcondition($respcondition);
00676                                                                 $found_answer = 0;
00677                                                                 foreach ($this->gaps[$respcondition_array["conditionvar"]["respident"]] as $key => $value)
00678                                                                 {
00679                                                                         if (strcmp($value->get_answertext(), $respcondition_array["conditionvar"]["value"]) == 0)
00680                                                                         {
00681                                                                                 $found_answer = 1;
00682                                                                                 $this->gaps[$respcondition_array["conditionvar"]["respident"]][$key]->set_points($respcondition_array["setvar"]["points"]);
00683                                                                                 if ($respcondition_array["conditionvar"]["selected"])
00684                                                                                 {
00685                                                                                         $this->gaps[$respcondition_array["conditionvar"]["respident"]][$key]->setChecked();
00686                                                                                 }
00687                                                                         }
00688                                                                 }
00689                                                                 if (!$found_answer)
00690                                                                 {
00691                                                                         // text gap
00692                                                                         array_push($this->gaps[$respcondition_array["conditionvar"]["respident"]], new ASS_AnswerCloze($respcondition_array["conditionvar"]["value"], $respcondition_array["setvar"]["points"], count($this->gaps[$respcondition_array["conditionvar"]["respident"]]), 1, CLOZE_TEXT, $respcondition_array["conditionvar"]["respident"], 0));
00693                                                                 }
00694                                                         }
00695                                                 }
00696                                                 break;
00697                                 }
00698                         }
00699                         $this->gaps = array_values($this->gaps);
00700                         $i = 0;
00701                         foreach ($materials as $key => $value)
00702                         {
00703                                 $this->cloze_text .= $value;
00704                                 $gaptext = $this->get_gap_text_list($i);
00705                                 if ($gaptext)
00706                                 {
00707                                         $type = " type=\"select\"";
00708                                         if ($this->gaps[$i][0]->get_cloze_type() == CLOZE_TEXT)
00709                                         {
00710                                                 $type = " type=\"text\"";
00711                                         }
00712                                         $shuffle = " shuffle=\"yes\"";
00713                                         if (!$this->gaps[$i][0]->get_shuffle())
00714                                         {
00715                                                 $shuffle = " shuffle=\"no\"";
00716                                         }
00717                                         $this->cloze_text .= "<gap$type$shuffle>$gaptext</gap>";
00718                                 }
00719                                 $i++;
00720                         }
00721                         $result = true;
00722                 }
00723                 return $result;
00724         }
00725 
00735         function to_xml($a_include_header = true, $a_include_binary = true, $a_shuffle = false, $test_output = false)
00736         {
00737                 if (!empty($this->domxml))
00738                 {
00739                         $this->domxml->free();
00740                 }
00741                 $xml_header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<questestinterop></questestinterop>\n";
00742                 $this->domxml = domxml_open_mem($xml_header);
00743                 $root = $this->domxml->document_element();
00744                 // qti ident
00745                 $qtiIdent = $this->domxml->create_element("item");
00746                 $qtiIdent->set_attribute("ident", "il_".IL_INST_ID."_qst_".$this->getId());
00747                 $qtiIdent->set_attribute("title", $this->getTitle());
00748                 $root->append_child($qtiIdent);
00749                 // add question description
00750                 $qtiComment = $this->domxml->create_element("qticomment");
00751                 $qtiCommentText = $this->domxml->create_text_node($this->getComment());
00752                 $qtiComment->append_child($qtiCommentText);
00753                 $qtiIdent->append_child($qtiComment);
00754                 // add estimated working time
00755                 $qtiDuration = $this->domxml->create_element("duration");
00756                 $workingtime = $this->getEstimatedWorkingTime();
00757                 $qtiDurationText = $this->domxml->create_text_node(sprintf("P0Y0M0DT%dH%dM%dS", $workingtime["h"], $workingtime["m"], $workingtime["s"]));
00758                 $qtiDuration->append_child($qtiDurationText);
00759                 $qtiIdent->append_child($qtiDuration);
00760 
00761                 // add ILIAS specific metadata
00762                 $qtiItemmetadata = $this->domxml->create_element("itemmetadata");
00763                 $qtiMetadata = $this->domxml->create_element("qtimetadata");
00764                 
00765                 $qtiMetadatafield = $this->domxml->create_element("qtimetadatafield");
00766                 $qtiFieldlabel = $this->domxml->create_element("fieldlabel");
00767                 $qtiFieldlabelText = $this->domxml->create_text_node("ILIAS_VERSION");
00768                 $qtiFieldlabel->append_child($qtiFieldlabelText);
00769                 $qtiFieldentry = $this->domxml->create_element("fieldentry");
00770                 $qtiFieldentryText = $this->domxml->create_text_node($this->ilias->getSetting("ilias_version"));
00771                 $qtiFieldentry->append_child($qtiFieldentryText);
00772                 $qtiMetadatafield->append_child($qtiFieldlabel);
00773                 $qtiMetadatafield->append_child($qtiFieldentry);
00774                 $qtiMetadata->append_child($qtiMetadatafield);
00775 
00776                 $qtiMetadatafield = $this->domxml->create_element("qtimetadatafield");
00777                 $qtiFieldlabel = $this->domxml->create_element("fieldlabel");
00778                 $qtiFieldlabelText = $this->domxml->create_text_node("QUESTIONTYPE");
00779                 $qtiFieldlabel->append_child($qtiFieldlabelText);
00780                 $qtiFieldentry = $this->domxml->create_element("fieldentry");
00781                 $qtiFieldentryText = $this->domxml->create_text_node(CLOZE_TEST_IDENTIFIER);
00782                 $qtiFieldentry->append_child($qtiFieldentryText);
00783                 $qtiMetadatafield->append_child($qtiFieldlabel);
00784                 $qtiMetadatafield->append_child($qtiFieldentry);
00785                 $qtiMetadata->append_child($qtiMetadatafield);
00786                 
00787                 $qtiMetadatafield = $this->domxml->create_element("qtimetadatafield");
00788                 $qtiFieldlabel = $this->domxml->create_element("fieldlabel");
00789                 $qtiFieldlabelText = $this->domxml->create_text_node("AUTHOR");
00790                 $qtiFieldlabel->append_child($qtiFieldlabelText);
00791                 $qtiFieldentry = $this->domxml->create_element("fieldentry");
00792                 $qtiFieldentryText = $this->domxml->create_text_node($this->getAuthor());
00793                 $qtiFieldentry->append_child($qtiFieldentryText);
00794                 $qtiMetadatafield->append_child($qtiFieldlabel);
00795                 $qtiMetadatafield->append_child($qtiFieldentry);
00796                 $qtiMetadata->append_child($qtiMetadatafield);
00797                 
00798                 $qtiItemmetadata->append_child($qtiMetadata);
00799                 $qtiIdent->append_child($qtiItemmetadata);
00800                 
00801                 // PART I: qti presentation
00802                 $qtiPresentation = $this->domxml->create_element("presentation");
00803                 $qtiPresentation->set_attribute("label", $this->getTitle());
00804                 // add flow to presentation
00805                 $qtiFlow = $this->domxml->create_element("flow");
00806 
00807                 $text_parts = preg_split("/<gap.*?<\/gap>/", $this->get_cloze_text());
00808                 // add material with question text to presentation
00809                 for ($i = 0; $i <= $this->get_gap_count(); $i++)
00810                 {
00811                         // n-th text part
00812                         $qtiMaterial = $this->domxml->create_element("material");
00813                         $qtiMatText = $this->domxml->create_element("mattext");
00814                         $qtiMatTextText = $this->domxml->create_text_node($text_parts[$i]);
00815                         $qtiMatText->append_child($qtiMatTextText);
00816                         $qtiMaterial->append_child($qtiMatText);
00817                         $qtiFlow->append_child($qtiMaterial);
00818 
00819                         if ($i < $this->get_gap_count())
00820                         {
00821                                 // add gap
00822                                 $gap = $this->get_gap($i);
00823                                 if ($gap[0]->get_cloze_type() == CLOZE_SELECT)
00824                                 {
00825                                         // comboboxes
00826                                         $qtiResponseStr = $this->domxml->create_element("response_str");
00827                                         $qtiResponseStr->set_attribute("ident", "gap_$i");
00828                                         $qtiResponseStr->set_attribute("rcardinality", "Single");
00829                                         $solution = $this->getSuggestedSolution($i);
00830                                         if (count($solution))
00831                                         {
00832                                                 if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $solution["internal_link"], $matches))
00833                                                 {
00834                                                         $qtiMaterial = $this->domxml->create_element("material");
00835                                                         $qtiMaterial->set_attribute("label", "suggested_solution");
00836                                                         $qtiMatText = $this->domxml->create_element("mattext");
00837                                                         $intlink = "il_" . IL_INST_ID . "_" . $matches[2] . "_" . $matches[3];
00838                                                         if (strcmp($matches[1], "") != 0)
00839                                                         {
00840                                                                 $intlink = $solution["internal_link"];
00841                                                         }
00842                                                         $qtiMatTextText = $this->domxml->create_text_node($intlink);
00843                                                         $qtiMatText->append_child($qtiMatTextText);
00844                                                         $qtiMaterial->append_child($qtiMatText);
00845                                                         $qtiResponseStr->append_child($qtiMaterial);
00846                                                 }
00847                                         }
00848                                         
00849                                         $qtiRenderChoice = $this->domxml->create_element("render_choice");
00850                                         // shuffle output
00851                                         if ($gap[0]->get_shuffle())
00852                                         {
00853                                                 $qtiRenderChoice->set_attribute("shuffle", "Yes");
00854                                         }
00855                                         else
00856                                         {
00857                                                 $qtiRenderChoice->set_attribute("shuffle", "No");
00858                                         }
00859 
00860                                         $gkeys = array_keys($gap);
00861                                         if ($gap[0]->get_shuffle() && $a_shuffle)
00862                                         {
00863                                                 $gkeys = $this->pcArrayShuffle($gkeys);
00864                                         }
00865 
00866                                         // add answers
00867                                         foreach ($gkeys as $key)
00868                                         {
00869                                                 $value = $gap[$key];
00870                                                 $qtiResponseLabel = $this->domxml->create_element("response_label");
00871                                                 $qtiResponseLabel->set_attribute("ident", $key);
00872                                                 $qtiMaterial = $this->domxml->create_element("material");
00873                                                 $qtiMatText = $this->domxml->create_element("mattext");
00874                                                 $tmpvalue = $value->get_answertext();
00875                                                 $qtiMatTextText = $this->domxml->create_text_node($tmpvalue);
00876                                                 $qtiMatText->append_child($qtiMatTextText);
00877                                                 $qtiMaterial->append_child($qtiMatText);
00878                                                 $qtiResponseLabel->append_child($qtiMaterial);
00879                                                 $qtiRenderChoice->append_child($qtiResponseLabel);
00880                                         }
00881                                         $qtiResponseStr->append_child($qtiRenderChoice);
00882                                         $qtiFlow->append_child($qtiResponseStr);
00883                                 }
00884                                 else
00885                                 {
00886                                         // text fields
00887                                         $qtiResponseStr = $this->domxml->create_element("response_str");
00888                                         $qtiResponseStr->set_attribute("ident", "gap_$i");
00889                                         $qtiResponseStr->set_attribute("rcardinality", "Single");
00890                                         $solution = $this->getSuggestedSolution($i);
00891                                         if (count($solution))
00892                                         {
00893                                                 if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $solution["internal_link"], $matches))
00894                                                 {
00895                                                         $qtiMaterial = $this->domxml->create_element("material");
00896                                                         $qtiMaterial->set_attribute("label", "suggested_solution");
00897                                                         $qtiMatText = $this->domxml->create_element("mattext");
00898                                                         $intlink = "il_" . IL_INST_ID . "_" . $matches[2] . "_" . $matches[3];
00899                                                         if (strcmp($matches[1], "") != 0)
00900                                                         {
00901                                                                 $intlink = $solution["internal_link"];
00902                                                         }
00903                                                         $qtiMatTextText = $this->domxml->create_text_node($intlink);
00904                                                         $qtiMatText->append_child($qtiMatTextText);
00905                                                         $qtiMaterial->append_child($qtiMatText);
00906                                                         $qtiResponseStr->append_child($qtiMaterial);
00907                                                 }
00908                                         }
00909                                         $qtiRenderFib = $this->domxml->create_element("render_fib");
00910                                         $qtiRenderFib->set_attribute("fibtype", "String");
00911                                         $qtiRenderFib->set_attribute("prompt", "Box");
00912                                         $qtiRenderFib->set_attribute("columns", $this->getColumnSize($gap));
00913                                         $qtiResponseLabel = $this->domxml->create_element("response_label");
00914                                         $qtiResponseLabel->set_attribute("ident", $i);
00915                                         $qtiRenderFib->append_child($qtiResponseLabel);
00916                                         $qtiResponseStr->append_child($qtiRenderFib);
00917                                         $qtiFlow->append_child($qtiResponseStr);
00918                                 }
00919                         }
00920                 }
00921                 $qtiPresentation->append_child($qtiFlow);
00922                 $qtiIdent->append_child($qtiPresentation);
00923 
00924                 // PART II: qti resprocessing
00925                 $qtiResprocessing = $this->domxml->create_element("resprocessing");
00926                 $qtiOutcomes = $this->domxml->create_element("outcomes");
00927                 $qtiDecvar = $this->domxml->create_element("decvar");
00928                 $qtiOutcomes->append_child($qtiDecvar);
00929                 $qtiResprocessing->append_child($qtiOutcomes);
00930                 // add response conditions
00931                 for ($i = 0; $i < $this->get_gap_count(); $i++)
00932                 {
00933                         $gap = $this->get_gap($i);
00934                         if ($gap[0]->get_cloze_type() == CLOZE_SELECT)
00935                         {
00936                                 foreach ($gap as $index => $answer)
00937                                 {
00938                                         $qtiRespcondition = $this->domxml->create_element("respcondition");
00939                                         $qtiRespcondition->set_attribute("continue", "Yes");
00940                                         // qti conditionvar
00941                                         $qtiConditionvar = $this->domxml->create_element("conditionvar");
00942 
00943                                         if (!$answer->isStateSet())
00944                                         {
00945                                                 $qtinot = $this->domxml->create_element("not");
00946                                         }
00947                                         
00948                                         $qtiVarequal = $this->domxml->create_element("varequal");
00949                                         $qtiVarequal->set_attribute("respident", "gap_$i");
00950                                         $qtiVarequalText = $this->domxml->create_text_node($answer->get_answertext());
00951                                         $qtiVarequal->append_child($qtiVarequalText);
00952                                         if (!$answer->isStateSet())
00953                                         {
00954                                                 $qtiConditionvar->append_child($qtinot);
00955                                                 $qtinot->append_child($qtiVarequal);
00956                                         }
00957                                         else
00958                                         {
00959                                                 $qtiConditionvar->append_child($qtiVarequal);
00960                                         }
00961                                         // qti setvar
00962                                         $qtiSetvar = $this->domxml->create_element("setvar");
00963                                         $qtiSetvar->set_attribute("action", "Add");
00964                                         $qtiSetvarText = $this->domxml->create_text_node($answer->get_points());
00965                                         $qtiSetvar->append_child($qtiSetvarText);
00966                                         // qti displayfeedback
00967                                         $qtiDisplayfeedback = $this->domxml->create_element("displayfeedback");
00968                                         $qtiDisplayfeedback->set_attribute("feedbacktype", "Response");
00969                                         $linkrefid = "";
00970                                         if ($answer->isStateSet())
00971                                         {
00972                                                 $linkrefid = "$i" . "_True";
00973                                         }
00974                                                 else
00975                                         {
00976                                                 $linkrefid = "$i" . "_False_$index";
00977                                         }
00978                                         $qtiDisplayfeedback->set_attribute("linkrefid", $linkrefid);
00979                                         $qtiRespcondition->append_child($qtiConditionvar);
00980                                         $qtiRespcondition->append_child($qtiSetvar);
00981                                         $qtiRespcondition->append_child($qtiDisplayfeedback);
00982                                         $qtiResprocessing->append_child($qtiRespcondition);
00983                                 }
00984                         }
00985                         else
00986                         {
00987                                 foreach ($gap as $index => $answer)
00988                                 {
00989                                         $qtiRespcondition = $this->domxml->create_element("respcondition");
00990                                         $qtiRespcondition->set_attribute("continue", "Yes");
00991                                         // qti conditionvar
00992                                         $qtiConditionvar = $this->domxml->create_element("conditionvar");
00993                                         $qtiVarequal = $this->domxml->create_element("varequal");
00994                                         $qtiVarequal->set_attribute("respident", "gap_$i");
00995                                         $qtiVarequalText = $this->domxml->create_text_node($answer->get_answertext());
00996                                         $qtiVarequal->append_child($qtiVarequalText);
00997                                         $qtiConditionvar->append_child($qtiVarequal);
00998                                         // qti setvar
00999                                         $qtiSetvar = $this->domxml->create_element("setvar");
01000                                         $qtiSetvar->set_attribute("action", "Add");
01001                                         $qtiSetvarText = $this->domxml->create_text_node($answer->get_points());
01002                                         $qtiSetvar->append_child($qtiSetvarText);
01003                                         // qti displayfeedback
01004                                         $qtiDisplayfeedback = $this->domxml->create_element("displayfeedback");
01005                                         $qtiDisplayfeedback->set_attribute("feedbacktype", "Response");
01006                                         $qtiDisplayfeedback->set_attribute("linkrefid", "$i" . "_True_$index");
01007                                         $qtiRespcondition->append_child($qtiConditionvar);
01008                                         $qtiRespcondition->append_child($qtiSetvar);
01009                                         $qtiRespcondition->append_child($qtiDisplayfeedback);
01010                                         $qtiResprocessing->append_child($qtiRespcondition);
01011                                 }
01012                         }
01013                 }
01014                 $qtiIdent->append_child($qtiResprocessing);
01015 
01016                 // PART III: qti itemfeedback
01017                 for ($i = 0; $i < $this->get_gap_count(); $i++)
01018                 {
01019                         $gap = $this->get_gap($i);
01020                         if ($gap[0]->get_cloze_type() == CLOZE_SELECT)
01021                         {
01022                                 foreach ($gap as $index => $answer)
01023                                 {
01024                                         $qtiItemfeedback = $this->domxml->create_element("itemfeedback");
01025                                         $linkrefid = "";
01026                                         if ($answer->isStateSet())
01027                                         {
01028                                                 $linkrefid = "$i" . "_True";
01029                                         }
01030                                                 else
01031                                         {
01032                                                 $linkrefid = "$i" . "_False_$index";
01033                                         }
01034                                         $qtiItemfeedback->set_attribute("ident", $linkrefid);
01035                                         $qtiItemfeedback->set_attribute("view", "All");
01036                                         // qti flow_mat
01037                                         $qtiFlowmat = $this->domxml->create_element("flow_mat");
01038                                         $qtiMaterial = $this->domxml->create_element("material");
01039                                         $qtiMattext = $this->domxml->create_element("mattext");
01040                                         // Insert response text for right/wrong answers here!!!
01041                                         $qtiMattextText = $this->domxml->create_text_node("");
01042                                         $qtiMattext->append_child($qtiMattextText);
01043                                         $qtiMaterial->append_child($qtiMattext);
01044                                         $qtiFlowmat->append_child($qtiMaterial);
01045                                         $qtiItemfeedback->append_child($qtiFlowmat);
01046                                         $qtiIdent->append_child($qtiItemfeedback);
01047                                 }
01048                         }
01049                         else
01050                         {
01051                                 foreach ($gap as $index => $answer)
01052                                 {
01053                                         $qtiItemfeedback = $this->domxml->create_element("itemfeedback");
01054                                         $linkrefid = "";
01055                                         if ($answer->isStateSet())
01056                                         {
01057                                                 $linkrefid = "$i" . "_True_$index";
01058                                         }
01059                                                 else
01060                                         {
01061                                                 $linkrefid = "$i" . "_False_$index";
01062                                         }
01063                                         $qtiItemfeedback->set_attribute("ident", $linkrefid);
01064                                         $qtiItemfeedback->set_attribute("view", "All");
01065                                         // qti flow_mat
01066                                         $qtiFlowmat = $this->domxml->create_element("flow_mat");
01067                                         $qtiMaterial = $this->domxml->create_element("material");
01068                                         $qtiMattext = $this->domxml->create_element("mattext");
01069                                         // Insert response text for right/wrong answers here!!!
01070                                         $qtiMattextText = $this->domxml->create_text_node("");
01071                                         $qtiMattext->append_child($qtiMattextText);
01072                                         $qtiMaterial->append_child($qtiMattext);
01073                                         $qtiFlowmat->append_child($qtiMaterial);
01074                                         $qtiItemfeedback->append_child($qtiFlowmat);
01075                                         $qtiIdent->append_child($qtiItemfeedback);
01076                                 }
01077                         }
01078                 }
01079 
01080                 $xml = $this->domxml->dump_mem(true);
01081                 if (!$a_include_header)
01082                 {
01083                         $pos = strpos($xml, "?>");
01084                         $xml = substr($xml, $pos + 2);
01085                 }
01086 //echo htmlentities($xml);
01087                 return $xml;
01088 
01089         }
01090 
01102         function set_cloze_text($cloze_text = "")
01103         {
01104                 $this->gaps = array();
01105                 $this->cloze_text =& $cloze_text;
01106                 $close = $this->createCloseTextArray();
01107                 if (count($close))
01108                 {
01109                         foreach ($close["gaps"] as $key => $value)
01110                         {
01111                                 if (strcmp(strtolower($value["params"]["type"]), "select") == 0)
01112                                 {
01113                                         $type = CLOZE_SELECT;
01114                                 }
01115                                         else
01116                                 {
01117                                         $type = CLOZE_TEXT;
01118                                 }
01119                                 if ($type == CLOZE_TEXT)
01120                                 {
01121                                         $default_state = 1;
01122                                 }
01123                                 else
01124                                 {
01125                                         $default_state = 0;
01126                                 }
01127                                 $name = $value["params"]["name"];
01128                                 if (strcmp(strtolower($value["params"]["shuffle"]), "no") == 0)
01129                                 {
01130                                         $shuffle = 0;
01131                                 }
01132                                         else
01133                                 {
01134                                         $shuffle = 1;
01135                                 }
01136                                 $answer_array = array();
01137                                 foreach ($value["text"] as $index => $textvalue)
01138                                 {
01139                                         if (preg_match("/\d+/", $index))
01140                                         {
01141                                                 $textvalue = str_replace("\,", ",", $textvalue);
01142                                                 array_push($answer_array, new ASS_AnswerCloze($textvalue, 0, $index, $default_state, $type, $name, $shuffle));
01143                                         }
01144                                 }
01145                                 array_push($this->gaps, $answer_array);
01146                         }
01147                 }
01148         }
01149 
01159   function get_cloze_text() {
01160     return $this->cloze_text;
01161   }
01162 
01172   function get_start_tag() {
01173     return $this->start_tag;
01174   }
01175 
01185   function get_end_tag() {
01186     return $this->end_tag;
01187   }
01188 
01198   function set_start_tag($start_tag = "<gap>") {
01199     $this->start_tag = $start_tag;
01200   }
01201 
01202 
01212   function set_end_tag($end_tag = "</gap>") {
01213     $this->end_tag = $end_tag;
01214   }
01215 
01224   function rebuild_cloze_text() 
01225         {
01226                 $close =& $this->createCloseTextArray();
01227                 if (count($close))
01228                 {
01229                         for ($i = 0; $i < count($this->gaps); $i++)
01230                         {
01231                                 $gaptext = $this->get_gap_text_list($i);
01232                                 $textparams = preg_split("/(?<!\\\\),/", $gaptext);
01233                                 $close["gaps"][$i]["text"] = array();
01234                                 $close["gaps"][$i]["text"]["text"] = $gaptext;
01235                                 foreach ($textparams as $key => $value)
01236                                 {
01237                                         $close["gaps"][$i]["text"][$key] = $value;
01238                                 }
01239                         }
01240                 }
01241                 $this->createCloseTextFromArray($close);
01242   }
01243 
01255   function get_gap($index = 0) {
01256     if ($index < 0) return array();
01257     if (count($this->gaps) < 1) return array();
01258     if ($index >= count($this->gaps)) return array();
01259     return $this->gaps[$index];
01260   }
01261 
01271   function get_gap_count() {
01272     return count($this->gaps);
01273   }
01274 
01287   function get_gap_text_list($index = 0, $separator = ",") {
01288     if ($index < 0) return "";
01289     if (count($this->gaps) < 1) return "";
01290     if ($index >= count($this->gaps)) return "";
01291     $result = array();
01292     foreach ($this->gaps[$index] as $key => $value) {
01293                         array_push($result, str_replace(",", "\,", $value->get_answertext()));
01294     }
01295     return join($separator, $result);
01296   }
01306   function get_gap_text_count($index = 0) {
01307     if ($index < 0) return 0;
01308     if (count($this->gaps) < 1) return 0;
01309     if ($index >= count($this->gaps)) return 0;
01310     return count($this->gaps[$index]);
01311   }
01322   function delete_gap($index = 0) {
01323     if ($index < 0) return;
01324     if (count($this->gaps) < 1) return;
01325     if ($index >= count($this->gaps)) return;
01326                 $close = $this->createCloseTextArray();
01327                 unset($close["gaps"][$index]);
01328                 $this->createCloseTextFromArray($close);
01329     unset($this->gaps[$index]);
01330     $this->gaps = array_values($this->gaps);
01331   }
01332 
01341   function flush_gaps() {
01342     $this->gaps = array();
01343   }
01344 
01356   function delete_answertext_by_index($gap_index = 0, $answertext_index = 0) {
01357     if ($gap_index < 0) return;
01358     if (count($this->gaps) < 1) return;
01359     if ($gap_index >= count($this->gaps)) return;
01360     $old_text = $this->get_gap_text_list($gap_index);
01361                 if (count($this->gaps[$gap_index]) == 1) {
01362                         $this->delete_gap($gap_index);
01363                 } else {
01364                         $close = $this->createCloseTextArray();
01365                         unset($this->gaps[$gap_index][$answertext_index]);
01366       $this->gaps[$gap_index] = array_values($this->gaps[$gap_index]);
01367                         unset($close["gaps"][$gap_index]["text"][$answertext_index]);
01368                         $this->createCloseTextFromArray($close);
01369                 }
01370   }
01371 
01384   function set_answertext($index = 0, $answertext_index = 0, $answertext = "", $add_gaptext=0) {
01385                 $answertext = str_replace("\,", ",", $answertext);
01386         if ($add_gaptext == 1)    {
01387         $arr = $this->gaps[$index][0];
01388         if (strlen($this->gaps[$index][count($this->gaps[$index])-1]->get_answertext()) != 0) {
01389                                 $default_state = 0;
01390                                 if ($arr->get_cloze_type() == CLOZE_TEXT)
01391                                 {
01392                                         $default_state = 1;
01393                                 }
01394                 array_push($this->gaps[$index], new ASS_AnswerCloze($answertext, 0, count($this->gaps[$index]),
01395                         $default_state, $arr->get_cloze_type(),
01396                         $arr->get_name(), $arr->get_shuffle()));
01397                 $this->rebuild_cloze_text();
01398         }
01399         return;
01400     }
01401     if ($index < 0) return;
01402     if (count($this->gaps) < 1) return;
01403     if ($index >= count($this->gaps)) return;
01404     if ($answertext_index < 0) return;
01405     if (count($this->gaps[$index]) < 1) return;
01406     if ($answertext_index >= count($this->gaps[$index])) return;
01407 
01408 
01409     if (strlen($answertext) == 0) {
01410       // delete the answertext
01411       $this->delete_answertext($index, $this->gaps[$index][$answertext_index]->get_answertext());
01412     } else {
01413       $this->gaps[$index][$answertext_index]->set_answertext($answertext);
01414       $this->rebuild_cloze_text();
01415     }
01416   }
01417 
01426         function update_all_gap_params() {
01427                 global $lng;
01428                 $close = $this->createCloseTextArray();
01429                 for ($i = 0; $i < $this->get_gap_count(); $i++)
01430                 {
01431                         $gaptext = $this->get_gap_text_list($i);
01432                         if ($this->gaps[$i][0]->get_cloze_type() == CLOZE_TEXT)
01433                         {
01434                                 $close["gaps"][$i]["params"]["type"] = "text";
01435                                 if (array_key_exists("shuffle", $close["gaps"][$i]["params"]))
01436                                 {
01437                                         unset($close["gaps"][$i]["params"]["shuffle"]);
01438                                 }
01439                         }
01440                                 else
01441                         {
01442                                 $close["gaps"][$i]["params"]["type"] = "select";
01443                                 if ($this->gaps[$i][0]->get_shuffle() == 0)
01444                                 {
01445                                         $close["gaps"][$i]["params"]["shuffle"] = "no";
01446                                 }
01447                                         else
01448                                 {
01449                                         $close["gaps"][$i]["params"]["shuffle"] = "yes";
01450                                 }
01451                         }
01452                         $name = $this->gaps[$i][0]->get_name();
01453                         if (!$name)
01454                         {
01455                                 $name = $this->lng->txt("gap") . " " . ($i+1);
01456                         }
01457                         $close["gaps"][$i]["params"]["name"] = $name;
01458                 }
01459                 $this->createCloseTextFromArray($close);
01460         }
01461 
01472         function set_cloze_type($index, $cloze_type = CLOZE_TEXT) {
01473     if ($index < 0) return;
01474     if (count($this->gaps) < 1) return;
01475     if ($index >= count($this->gaps)) return;
01476                 $close = $this->createCloseTextArray();
01477                 foreach ($this->gaps[$index] as $key => $value) {
01478                         $this->gaps[$index][$key]->set_cloze_type($cloze_type);
01479                         $this->gaps[$index][$key]->setState(1);
01480                 }
01481                 if ($cloze_type == CLOZE_TEXT)
01482                 {
01483                         $type = "text";
01484                 }
01485                 else
01486                 {
01487                         $type = "select";
01488                 }
01489                 $close["gaps"][$index]["type"] = $type;
01490                 $this->createCloseTextFromArray($close);
01491         }
01492 
01504   function set_gap_points($index = 0, $points = 0.0) {
01505     if ($index < 0) return;
01506     if (count($this->gaps) < 1) return;
01507     if ($index >= count($this->gaps)) return;
01508     foreach ($this->gaps[$index] as $key => $value) {
01509       $this->gaps[$index][$key]->set_points($points);
01510     }
01511   }
01512 
01524   function set_gap_shuffle($index = 0, $shuffle = 1) {
01525     if ($index < 0) return;
01526     if (count($this->gaps) < 1) return;
01527     if ($index >= count($this->gaps)) return;
01528     foreach ($this->gaps[$index] as $key => $value) {
01529       $this->gaps[$index][$key]->set_shuffle($shuffle);
01530     }
01531   }
01532 
01533 
01546   function set_single_answer_points($index_gaps = 0, $index_answerobject = 0, $points = 0.0) {
01547     if ($index_gaps < 0) return;
01548     if (count($this->gaps) < 1) return;
01549     if ($index_gaps >= count($this->gaps)) return;
01550     if ($index_answerobject < 0) return;
01551     if (count($this->gaps[$index_gaps]) < 1) return;
01552     if ($index_answerobject >= count($this->gaps[$index_gaps])) return;
01553     $this->gaps[$index_gaps][$index_answerobject]->set_points($points);
01554   }
01555 
01568   function set_single_answer_state($index_gaps = 0, $index_answerobject = 0, $state = 0) {
01569     if ($index_gaps < 0) return;
01570     if (count($this->gaps) < 1) return;
01571     if ($index_gaps >= count($this->gaps)) return;
01572     if ($index_answerobject < 0) return;
01573     if (count($this->gaps[$index_gaps]) < 1) return;
01574     if ($index_answerobject >= count($this->gaps[$index_gaps])) return;
01575     $this->gaps[$index_gaps][$index_answerobject]->setState($state);
01576   }
01577         
01589         function calculateReachedPoints($user_id, $test_id)
01590         {
01591                 global $ilDB;
01592                 
01593     $found_value1 = array();
01594     $found_value2 = array();
01595     $query = sprintf("SELECT * FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
01596       $ilDB->quote($user_id),
01597       $ilDB->quote($test_id),
01598       $ilDB->quote($this->getId())
01599     );
01600     $result = $ilDB->query($query);
01601                 $user_result = array();
01602     while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
01603                         if (strcmp($data->value2, "") != 0)
01604                         {
01605                                 $user_result[$data->value1] = array(
01606                                         "gap_id" => $data->value1,
01607                                         "value" => $data->value2
01608                                 );
01609                         }
01610     }
01611     $points = 0;
01612     $counter = 0;
01613                 foreach ($user_result as $gap_id => $value) {
01614                         if ($this->gaps[$gap_id][0]->get_cloze_type() == CLOZE_TEXT) 
01615                         {
01616                                 $foundsolution = 0;
01617                                 foreach ($this->gaps[$gap_id] as $k => $v) {
01618                                         if ((strcmp(strtolower($v->get_answertext()), strtolower($value["value"])) == 0) && (!$foundsolution)) {
01619                                                 $points += $v->get_points();
01620                                                 $foundsolution = 1;
01621                                         }
01622                                 }
01623                         } 
01624                         else 
01625                         {
01626                                 if ($value["value"] >= 0)
01627                                 {
01628                                         foreach ($this->gaps[$gap_id] as $answerkey => $answer)
01629                                         {
01630                                                 if ($value["value"] == $answerkey)
01631                                                 {
01632                                                         $points += $answer->get_points();
01633                                                 }
01634                                         }
01635                                 }
01636                         }
01637     }
01638 
01639                 // check for special scoring options in test
01640                 $query = sprintf("SELECT * FROM tst_tests WHERE test_id = %s",
01641                         $ilDB->quote($test_id)
01642                 );
01643                 $result = $ilDB->query($query);
01644                 if ($result->numRows() == 1)
01645                 {
01646                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
01647                         if ($row["count_system"] == 1)
01648                         {
01649                                 if ($points != $this->getMaximumPoints())
01650                                 {
01651                                         $points = 0;
01652                                 }
01653                         }
01654                 }
01655                 else
01656                 {
01657                         $points = 0;
01658                 }
01659                 return $points;
01660         }
01661 
01671   function getReachedInformation($user_id, $test_id) {
01672     $found_value1 = array();
01673     $found_value2 = array();
01674     $query = sprintf("SELECT * FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
01675       $this->ilias->db->quote($user_id),
01676       $this->ilias->db->quote($test_id),
01677       $this->ilias->db->quote($this->getId())
01678     );
01679     $result = $this->ilias->db->query($query);
01680     while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
01681       array_push($found_value1, $data->value1);
01682       array_push($found_value2, $data->value2);
01683     }
01684     $counter = 1;
01685                 $user_result = array();
01686     foreach ($found_value1 as $key => $value) {
01687       if ($this->gaps[$value][0]->get_cloze_type() == CLOZE_TEXT) 
01688                         {
01689                                 $solution = array(
01690                                         "gap" => "$counter",
01691                                         "points" => 0,
01692                                         "true" => 0,
01693                                         "value" => $found_value2[$key]
01694                                 );
01695         foreach ($this->gaps[$value] as $k => $v) {
01696           if (strcmp(strtolower($v->get_answertext()), strtolower($found_value2[$key])) == 0) {
01697                                                 $solution = array(
01698                                                         "gap" => "$counter",
01699                                                         "points" => $v->get_points(),
01700                                                         "true" => 1,
01701                                                         "value" => $found_value2[$key]
01702                                                 );
01703           }
01704         }
01705       } 
01706                         else 
01707                         {
01708                                 $solution = array(
01709                                         "gap" => "$counter",
01710                                         "points" => 0,
01711                                         "true" => 0,
01712                                         "value" => $found_value2[$key]
01713                                 );
01714         if ($this->gaps[$value][$found_value1[$key]]->isStateSet()) {
01715                                         $solution["points"] = $this->gaps[$value][$found_value1[$key]]->get_points();
01716                                         $solution["true"] = 1;
01717         }
01718       }
01719                         $counter++;
01720                         $user_result[$value] = $solution;
01721     }
01722     return $user_result;
01723   }
01724 
01733   function getMaximumPoints() {
01734     $points = 0;
01735     foreach ($this->gaps as $key => $value) {
01736       if ($value[0]->get_cloze_type() == CLOZE_TEXT) {
01737         $points += $value[0]->get_points();
01738       } else {
01739                                 $points_arr = array("set" => 0, "unset" => 0);
01740         foreach ($value as $key2 => $value2) {
01741                                         if ($value2->get_points() > $points_arr["set"])
01742                                         {
01743                                                 $points_arr["set"] = $value2->get_points();
01744                                         }
01745                                 }
01746                                 $points += $points_arr["set"];
01747       }
01748     }
01749     return $points;
01750   }
01751 
01762   function saveWorkingData($test_id, $limit_to = LIMIT_NO_LIMIT) {
01763     global $ilDB;
01764                 global $ilUser;
01765     $db =& $ilDB->db;
01766 
01767     $query = sprintf("DELETE FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
01768       $db->quote($ilUser->id),
01769       $db->quote($test_id),
01770       $db->quote($this->getId())
01771     );
01772     $result = $db->query($query);
01773 
01774     foreach ($_POST as $key => $value) {
01775       if (preg_match("/^gap_(\d+)/", $key, $matches)) {
01776         $query = sprintf("INSERT INTO tst_solutions (solution_id, user_fi, test_fi, question_fi, value1, value2, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, NULL)",
01777                                         $db->quote($ilUser->id),
01778                                         $db->quote($test_id),
01779           $db->quote($this->getId()),
01780           $db->quote($matches[1]),
01781           $db->quote(ilUtil::stripSlashes($value))
01782         );
01783         $result = $db->query($query);
01784       }
01785     }
01786     parent::saveWorkingData($test_id);
01787                 return true;
01788   }
01789 
01790         function syncWithOriginal()
01791         {
01792                 global $ilias;
01793                 if ($this->original_id)
01794                 {
01795                         $complete = 0;
01796                         if ($this->isComplete())
01797                         {
01798                                 $complete = 1;
01799                         }
01800                         $db = & $ilias->db;
01801         
01802                         $estw_time = $this->getEstimatedWorkingTime();
01803                         $estw_time = sprintf("%02d:%02d:%02d", $estw_time['h'], $estw_time['m'], $estw_time['s']);
01804         
01805                         $query = sprintf("UPDATE qpl_questions SET obj_fi = %s, title = %s, comment = %s, points = %s, author = %s, question_text = %s, working_time = %s, shuffle = %s, complete = %s WHERE question_id = %s",
01806                                 $db->quote($this->obj_id. ""),
01807                                 $db->quote($this->title . ""),
01808                                 $db->quote($this->comment . ""),
01809                                 $db->quote($this->getMaximumPoints() . ""),
01810                                 $db->quote($this->author . ""),
01811                                 $db->quote($this->cloze_text . ""),
01812                                 $db->quote($estw_time . ""),
01813                                 $db->quote($this->shuffle . ""),
01814                                 $db->quote($complete . ""),
01815                                 $db->quote($this->original_id . "")
01816                                 );
01817                         $result = $db->query($query);
01818 
01819                         if ($result == DB_OK)
01820                         {
01821                                 // write answers
01822                                 // delete old answers
01823                                 $query = sprintf("DELETE FROM qpl_answers WHERE question_fi = %s",
01824                                         $db->quote($this->original_id)
01825                                 );
01826                                 $result = $db->query($query);
01827         
01828                                 foreach ($this->gaps as $key => $value)
01829                                 {
01830                                         foreach ($value as $answer_id => $answer_obj)
01831                                         {
01832                                                 $query = sprintf("INSERT INTO qpl_answers (answer_id, question_fi, gap_id, answertext, points, aorder, cloze_type, name, shuffle, correctness, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
01833                                                         $db->quote($this->original_id . ""),
01834                                                         $db->quote($key . ""),
01835                                                         $db->quote($answer_obj->get_answertext() . ""),
01836                                                         $db->quote($answer_obj->get_points() . ""),
01837                                                         $db->quote($answer_obj->get_order() . ""),
01838                                                         $db->quote($answer_obj->get_cloze_type() . ""),
01839                                                         $db->quote($answer_obj->get_name() . ""),
01840                                                         $db->quote($answer_obj->get_shuffle() . ""),
01841                                                         $db->quote($answer_obj->getState() . "")
01842                                                         );
01843                                                 $answer_result = $db->query($query);
01844                                         }
01845                                 }
01846                         }
01847                         parent::syncWithOriginal();
01848                 }
01849         }
01850 
01859         function getQuestionType()
01860         {
01861                 return 3;
01862         }
01863         
01872         function getColumnSize($gap)
01873         {
01874                 $size = 0;
01875                 foreach ($gap as $answer)
01876                 {
01877                         $answertextsize = strlen($answer->get_answertext());
01878                         if ($answertextsize > $size) $size = $answertextsize;
01879                 }
01880                 return $size;
01881         }
01882 }
01883 
01884 ?>

Generated on Fri Dec 13 2013 10:18:25 for ILIAS Release_3_5_x_branch .rev 46805 by  doxygen 1.7.1