• 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 include_once "./assessment/classes/class.assQuestion.php";
00025 include_once "./assessment/classes/inc.AssessmentConstants.php";
00026 
00037 class ASS_ClozeTest extends ASS_Question
00038 {
00047         var $cloze_text;
00048 
00056         var $gaps;
00057 
00065         var $start_tag;
00066 
00074         var $end_tag;
00075         
00086         var $textgap_rating;
00087         
00100         function ASS_ClozeTest(
00101                 $title = "",
00102                 $comment = "",
00103                 $author = "",
00104                 $owner = -1,
00105                 $cloze_text = ""
00106         )
00107         {
00108                 $this->start_tag = "<gap>";
00109                 $this->end_tag = "</gap>";
00110                 $this->ASS_Question($title, $comment, $author, $owner);
00111                 $this->gaps = array();
00112                 $this->set_cloze_text($cloze_text);
00113         }
00114 
00123         function isComplete()
00124         {
00125                 if (($this->title) and ($this->author) and ($this->cloze_text) and (count($this->gaps)) and ($this->getMaximumPoints() > 0))
00126                 {
00127                         return true;
00128                 }
00129                 else
00130                 {
00131                         return false;
00132                 }
00133         }
00134 
00143         function &createCloseTextArray()
00144         {
00145                 $result = array();
00146                 $search_pattern = "|<gap([^>]*?)>(.*?)</gap>|i";
00147                 preg_match_all($search_pattern, $this->cloze_text, $gaps);
00148                 if (count($gaps[0]))
00149                 {
00150                         // found at least one gap
00151                         $delimiters = preg_split($search_pattern, $this->cloze_text, -1, PREG_SPLIT_OFFSET_CAPTURE);
00152                         $result["gaps"] = array();
00153                         foreach ($gaps[0] as $index => $gap)
00154                         {
00155                                 $result["gaps"][$index] = array();
00156                                 $result["gaps"][$index]["gap"] = $gap;
00157                                 $result["gaps"][$index]["params"] = array();
00158                                 $result["gaps"][$index]["params"]["text"] = $gaps[1][$index];
00159                                 // separate gap params
00160                                 if (preg_match("/name\=\"([^\"]*?)\"/", $gaps[1][$index], $params))
00161                                 {
00162                                         $result["gaps"][$index]["params"]["name"] = $params[1];
00163                                 }
00164                                 else
00165                                 {
00166                                         $result["gaps"][$index]["params"]["name"] = $this->lng->txt("gap") . " " . ($index+1);
00167                                 }
00168                                 if (preg_match("/type\=\"([^\"]*?)\"/", $gaps[1][$index], $params))
00169                                 {
00170                                         $result["gaps"][$index]["params"]["type"] = $params[1];
00171                                 }
00172                                 else
00173                                 {
00174                                         $result["gaps"][$index]["params"]["type"] = "text";
00175                                 }
00176                                 if (preg_match("/shuffle\=\"([^\"]*?)\"/", $gaps[1][$index], $params))
00177                                 {
00178                                         $result["gaps"][$index]["params"]["shuffle"] = $params[1];
00179                                 }
00180                                 else
00181                                 {
00182                                         if (strcmp(strtolower($result["gaps"][$index]["params"]["type"]), "select") == 0)
00183                                         {
00184                                                 $result["gaps"][$index]["params"]["shuffle"] = "yes";
00185                                         }
00186                                 }
00187                                 $result["gaps"][$index]["text"] = array();
00188                                 $result["gaps"][$index]["text"]["text"] = $gaps[2][$index];
00189                                 $textparams = preg_split("/(?<!\\\\),/", $gaps[2][$index]);
00190                                 foreach ($textparams as $key => $value)
00191                                 {
00192                                         $result["gaps"][$index]["text"][$key] = $value;
00193                                 }
00194                         }
00195                         $result["delimiters"] = $delimiters;
00196                 }
00197                 else
00198                 {
00199                         $result["gaps"] = array();
00200                         $result["delimiters"] = 
00201                                 array(
00202                                         array(0 => $this->cloze_text, 1 => "0")
00203                                 );
00204                 }
00205                 //echo str_replace("\n", "<br />", str_replace(" ", "&nbsp;", ilUtil::prepareFormOutput(print_r($result, true))));
00206                 return $result;         
00207         }
00208 
00217         function createCloseTextFromArray($assoc_array)
00218         {
00219                 $this->cloze_text = "";
00220                 if (count($assoc_array))
00221                 {
00222                         $gap = 0;
00223                         foreach ($assoc_array["delimiters"] as $key => $value)
00224                         {
00225                                 if (($key > 0) && ($key < count($assoc_array["delimiters"])))
00226                                 {
00227                                         if (strcmp($assoc_array["gaps"][$gap]["params"]["shuffle"], "") == 0)
00228                                         {
00229                                                 $shuffle = "";
00230                                         }
00231                                         else
00232                                         {
00233                                                 $shuffle = " shuffle=\"" . $assoc_array["gaps"][$gap]["params"]["shuffle"] . "\"";
00234                                         }
00235                                         $textarray = array();
00236                                         if (is_array($assoc_array["gaps"][$gap]["text"]))
00237                                         {
00238                                                 foreach ($assoc_array["gaps"][$gap]["text"] as $textindex => $textvalue)
00239                                                 {
00240                                                         if (preg_match("/\d+/", $textindex))
00241                                                         {
00242                                                                 array_push($textarray, $textvalue);
00243                                                         }
00244                                                 }
00245                                         }
00246                                         if (count($textarray))
00247                                         {
00248                                                 $this->cloze_text .= sprintf("<gap name=\"%s\" type=\"%s\"%s>%s</gap>",
00249                                                         $assoc_array["gaps"][$gap]["params"]["name"],
00250                                                         $assoc_array["gaps"][$gap]["params"]["type"],
00251                                                         $shuffle,
00252                                                         join(",", $textarray)
00253                                                 );
00254                                         }
00255                                         $gap++;
00256                                 }
00257                                 $this->cloze_text .= $value[0];
00258                         }
00259                 }
00260         }
00261         
00270         function saveToDb($original_id = "")
00271         {
00272                 global $ilias;
00273 
00274                 $db =& $ilias->db;
00275                 $complete = 0;
00276                 if ($this->isComplete())
00277                 {
00278                         $complete = 1;
00279                 }
00280 
00281                 $estw_time = $this->getEstimatedWorkingTime();
00282                 $estw_time = sprintf("%02d:%02d:%02d", $estw_time['h'], $estw_time['m'], $estw_time['s']);
00283                 $shuffle = 1;
00284 
00285                 if (!$this->shuffle)
00286                 {
00287                         $shuffle = 0;
00288                 }
00289 
00290                 if ($original_id)
00291                 {
00292                         $original_id = $db->quote($original_id);
00293                 }
00294                 else
00295                 {
00296                         $original_id = "NULL";
00297                 }
00298 
00299                 if ($this->id == -1)
00300                 {
00301                         // Neuen Datensatz schreiben
00302                         $now = getdate();
00303                         $created = sprintf("%04d%02d%02d%02d%02d%02d", $now['year'], $now['mon'], $now['mday'], $now['hours'], $now['minutes'], $now['seconds']);
00304                         $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, textgap_rating, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
00305                                 $db->quote($this->getQuestionType()),
00306                                 $db->quote($this->obj_id),
00307                                 $db->quote($this->title),
00308                                 $db->quote($this->comment),
00309                                 $db->quote($this->getMaximumPoints() . ""),
00310                                 $db->quote($this->author),
00311                                 $db->quote($this->owner),
00312                                 $db->quote($this->cloze_text),
00313                                 $db->quote($estw_time),
00314                                 $db->quote("$this->shuffle"),
00315                                 $db->quote("$complete"),
00316                                 $db->quote($created),
00317                                 $original_id,
00318                                 $db->quote($this->textgap_rating)
00319                         );
00320                         $result = $db->query($query);
00321                         if ($result == DB_OK)
00322                         {
00323                                 $this->id = $this->ilias->db->getLastInsertId();
00324 
00325                                 // create page object of question
00326                                 $this->createPageObject();
00327 
00328                                 // Falls die Frage in einen Test eingef�gt werden soll, auch diese Verbindung erstellen
00329                                 if ($this->getTestId() > 0)
00330                                 {
00331                                         $this->insertIntoTest($this->getTestId());
00332                                 }
00333                         }
00334                 }
00335                 else
00336                 {
00337                         // Vorhandenen Datensatz aktualisieren
00338                         $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, textgap_rating = %s WHERE question_id = %s",
00339                                 $db->quote($this->obj_id. ""),
00340                                 $db->quote($this->title),
00341                                 $db->quote($this->comment),
00342                                 $db->quote($this->getMaximumPoints() . ""),
00343                                 $db->quote($this->author),
00344                                 $db->quote($this->cloze_text),
00345                                 $db->quote($estw_time),
00346                                 $db->quote("$this->shuffle"),
00347                                 $db->quote("$complete"),
00348                                 $db->quote($this->textgap_rating),
00349                                 $db->quote($this->id)
00350                                 );
00351                         $result = $db->query($query);
00352                 }
00353 
00354                 if ($result == DB_OK)
00355                 {
00356                         // Antworten schreiben
00357 
00358                         // delete old answers
00359                         $query = sprintf("DELETE FROM qpl_answers WHERE question_fi = %s",
00360                                 $db->quote($this->id)
00361                         );
00362                         $result = $db->query($query);
00363                         // Anworten wegschreiben
00364                         foreach ($this->gaps as $key => $value)
00365                         {
00366                                 foreach ($value as $answer_id => $answer_obj)
00367                                 {
00368                                         $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)",
00369                                                 $db->quote($this->id),
00370                                                 $db->quote($key),
00371                                                 $db->quote($answer_obj->get_answertext() . ""),
00372                                                 $db->quote($answer_obj->get_points() . ""),
00373                                                 $db->quote($answer_obj->get_order() . ""),
00374                                                 $db->quote($answer_obj->get_cloze_type() . ""),
00375                                                 $db->quote($answer_obj->get_name() . ""),
00376                                                 $db->quote($answer_obj->get_shuffle() . ""),
00377                                                 $db->quote($answer_obj->getState() . "")
00378                                                 );
00379                                         $answer_result = $db->query($query);
00380                                 }
00381                         }
00382                 }
00383                 parent::saveToDb($original_id);
00384         }
00385 
00395   function loadFromDb($question_id)
00396   {
00397     global $ilias;
00398     $db =& $ilias->db;
00399 
00400                 include_once "./assessment/classes/class.assAnswerCloze.php";
00401     $query = sprintf("SELECT * FROM qpl_questions WHERE question_id = %s",
00402       $db->quote($question_id)
00403     );
00404     $result = $db->query($query);
00405     if (strcmp(strtolower(get_class($result)), db_result) == 0) {
00406       if ($result->numRows() == 1) {
00407         $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
00408         $this->id = $question_id;
00409         $this->obj_id = $data->obj_fi;
00410         $this->title = $data->title;
00411         $this->comment = $data->comment;
00412                                 $this->solution_hint = $data->solution_hint;
00413                                 $this->original_id = $data->original_id;
00414         $this->author = $data->author;
00415                                 $this->points = $data->points;
00416         $this->owner = $data->owner;
00417         $this->cloze_text = $data->question_text;
00418                                 $this->setTextgapRating($data->textgap_rating);
00419                                 $this->shuffle = $data->shuffle;
00420         $this->setEstimatedWorkingTime(substr($data->working_time, 0, 2), substr($data->working_time, 3, 2), substr($data->working_time, 6, 2));
00421       }
00422 
00423       $query = sprintf("SELECT * FROM qpl_answers WHERE question_fi = %s ORDER BY gap_id, aorder ASC",
00424         $db->quote($question_id)
00425       );
00426       $result = $db->query($query);
00427       if (strcmp(strtolower(get_class($result)), db_result) == 0) {
00428         $counter = -1;
00429         while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
00430           if ($data->gap_id != $counter) {
00431             $answer_array = array();
00432             array_push($this->gaps, $answer_array);
00433             $counter = $data->gap_id;
00434           }
00435                                         if ($data->cloze_type == CLOZE_SELECT)
00436                                         {
00437                                                 if ($data->correctness == 0)
00438                                                 {
00439                                                         // fix for older single response answers where points could be given for unchecked answers
00440                                                         $data->correctness = 1;
00441                                                         $data->points = 0;
00442                                                 }
00443                                         }
00444           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));
00445         }
00446       }
00447     }
00448                 parent::loadFromDb($question_id);
00449   }
00450         
00458         function addAnswer($gap, $answertext, $points, $answerorder, $correctness, $clozetype, $name, $shuffle, $answer_id = -1)
00459         {
00460                 include_once "./assessment/classes/class.assAnswerCloze.php";
00461                 if (!is_array($this->gaps[$gap]))
00462                 {
00463                         $this->gaps[$gap] = array();
00464                 }
00465                 array_push($this->gaps[$gap], new ASS_AnswerCloze($answertext, $points, $answerorder, $correctness, $clozetype, $name, $shuffle, $answer_id));
00466         }
00467         
00475         function duplicate($for_test = true, $title = "", $author = "", $owner = "")
00476         {
00477                 if ($this->id <= 0)
00478                 {
00479                         // The question has not been saved. It cannot be duplicated
00480                         return;
00481                 }
00482                 // duplicate the question in database
00483                 $this_id = $this->getId();
00484                 $clone = $this;
00485                 include_once ("./assessment/classes/class.assQuestion.php");
00486                 $original_id = ASS_Question::_getOriginalId($this->id);
00487                 $clone->id = -1;
00488                 if ($title)
00489                 {
00490                         $clone->setTitle($title);
00491                 }
00492                 if ($author)
00493                 {
00494                         $clone->setAuthor($author);
00495                 }
00496                 if ($owner)
00497                 {
00498                         $clone->setOwner($owner);
00499                 }
00500                 if ($for_test)
00501                 {
00502                         $clone->saveToDb($original_id);
00503                 }
00504                 else
00505                 {
00506                         $clone->saveToDb();
00507                 }
00508 
00509                 // copy question page content
00510                 $clone->copyPageOfQuestion($this_id);
00511 
00512                 return $clone->id;
00513         }
00514 
00522         function copyObject($target_questionpool, $title = "")
00523         {
00524                 if ($this->id <= 0)
00525                 {
00526                         // The question has not been saved. It cannot be duplicated
00527                         return;
00528                 }
00529                 // duplicate the question in database
00530                 $clone = $this;
00531                 include_once ("./assessment/classes/class.assQuestion.php");
00532                 $original_id = ASS_Question::_getOriginalId($this->id);
00533                 $clone->id = -1;
00534                 $source_questionpool = $this->getObjId();
00535                 $clone->setObjId($target_questionpool);
00536                 if ($title)
00537                 {
00538                         $clone->setTitle($title);
00539                 }
00540                 $clone->saveToDb();
00541 
00542                 // copy question page content
00543                 $clone->copyPageOfQuestion($original_id);
00544 
00545                 return $clone->id;
00546         }
00547         
00557         function to_xml($a_include_header = true, $a_include_binary = true, $a_shuffle = false, $test_output = false, $force_image_references = false)
00558         {
00559                 include_once("./classes/class.ilXmlWriter.php");
00560                 $a_xml_writer = new ilXmlWriter;
00561                 // set xml header
00562                 $a_xml_writer->xmlHeader();
00563                 $a_xml_writer->xmlStartTag("questestinterop");
00564                 $attrs = array(
00565                         "ident" => "il_".IL_INST_ID."_qst_".$this->getId(),
00566                         "title" => $this->getTitle()
00567                 );
00568                 $a_xml_writer->xmlStartTag("item", $attrs);
00569                 // add question description
00570                 $a_xml_writer->xmlElement("qticomment", NULL, $this->getComment());
00571                 // add estimated working time
00572                 $workingtime = $this->getEstimatedWorkingTime();
00573                 $duration = sprintf("P0Y0M0DT%dH%dM%dS", $workingtime["h"], $workingtime["m"], $workingtime["s"]);
00574                 $a_xml_writer->xmlElement("duration", NULL, $duration);
00575                 // add ILIAS specific metadata
00576                 $a_xml_writer->xmlStartTag("itemmetadata");
00577                 $a_xml_writer->xmlStartTag("qtimetadata");
00578                 $a_xml_writer->xmlStartTag("qtimetadatafield");
00579                 $a_xml_writer->xmlElement("fieldlabel", NULL, "ILIAS_VERSION");
00580                 $a_xml_writer->xmlElement("fieldentry", NULL, $this->ilias->getSetting("ilias_version"));
00581                 $a_xml_writer->xmlEndTag("qtimetadatafield");
00582                 $a_xml_writer->xmlStartTag("qtimetadatafield");
00583                 $a_xml_writer->xmlElement("fieldlabel", NULL, "QUESTIONTYPE");
00584                 $a_xml_writer->xmlElement("fieldentry", NULL, CLOZE_TEST_IDENTIFIER);
00585                 $a_xml_writer->xmlEndTag("qtimetadatafield");
00586                 $a_xml_writer->xmlStartTag("qtimetadatafield");
00587                 $a_xml_writer->xmlElement("fieldlabel", NULL, "AUTHOR");
00588                 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAuthor());
00589                 $a_xml_writer->xmlEndTag("qtimetadatafield");
00590                 $a_xml_writer->xmlStartTag("qtimetadatafield");
00591                 $a_xml_writer->xmlElement("fieldlabel", NULL, "textgaprating");
00592                 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getTextgapRating());
00593                 $a_xml_writer->xmlEndTag("qtimetadatafield");
00594                 $a_xml_writer->xmlEndTag("qtimetadata");
00595                 $a_xml_writer->xmlEndTag("itemmetadata");
00596                 
00597                 // PART I: qti presentation
00598                 $attrs = array(
00599                         "label" => $this->getTitle()
00600                 );
00601                 $a_xml_writer->xmlStartTag("presentation", $attrs);
00602                 // add flow to presentation
00603                 $a_xml_writer->xmlStartTag("flow");
00604                 $text_parts = preg_split("/<gap.*?<\/gap>/", $this->get_cloze_text());
00605                 // add material with question text to presentation
00606                 for ($i = 0; $i <= $this->get_gap_count(); $i++)
00607                 {
00608                         // n-th text part
00609                         $a_xml_writer->xmlStartTag("material");
00610                         $a_xml_writer->xmlElement("mattext", NULL, $text_parts[$i]);
00611                         $a_xml_writer->xmlEndTag("material");
00612 
00613                         if ($i < $this->get_gap_count())
00614                         {
00615                                 // add gap
00616                                 $gap = $this->get_gap($i);
00617                                 if ($gap[0]->get_cloze_type() == CLOZE_SELECT)
00618                                 {
00619                                         // comboboxes
00620                                         $attrs = array(
00621                                                 "ident" => "gap_$i",
00622                                                 "rcardinality" => "Single"
00623                                         );
00624                                         $a_xml_writer->xmlStartTag("response_str", $attrs);
00625                                         $solution = $this->getSuggestedSolution($i);
00626                                         if (count($solution))
00627                                         {
00628                                                 if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $solution["internal_link"], $matches))
00629                                                 {
00630                                                         $attrs = array(
00631                                                                 "label" => "suggested_solution"
00632                                                         );
00633                                                         $a_xml_writer->xmlStartTag("material", $attrs);
00634                                                         $intlink = "il_" . IL_INST_ID . "_" . $matches[2] . "_" . $matches[3];
00635                                                         if (strcmp($matches[1], "") != 0)
00636                                                         {
00637                                                                 $intlink = $solution["internal_link"];
00638                                                         }
00639                                                         $a_xml_writer->xmlElement("mattext", NULL, $intlink);
00640                                                         $a_xml_writer->xmlEndTag("material");
00641                                                 }
00642                                         }
00643                                         
00644                                         $attrs = array();
00645                                         if ($gap[0]->get_shuffle())
00646                                         {
00647                                                 $attrs = array("shuffle" => "Yes");
00648                                         }
00649                                         else
00650                                         {
00651                                                 $attrs = array("shuffle" => "No");
00652                                         }
00653                                         $a_xml_writer->xmlStartTag("render_choice", $attrs);
00654 
00655                                         // shuffle output
00656                                         $gkeys = array_keys($gap);
00657                                         if ($gap[0]->get_shuffle() && $a_shuffle)
00658                                         {
00659                                                 $gkeys = $this->pcArrayShuffle($gkeys);
00660                                         }
00661 
00662                                         // add answers
00663                                         foreach ($gkeys as $key)
00664                                         {
00665                                                 $value = $gap[$key];
00666                                                 $attrs = array(
00667                                                         "ident" => $key
00668                                                 );
00669                                                 $a_xml_writer->xmlStartTag("response_label", $attrs);
00670                                                 $a_xml_writer->xmlStartTag("material");
00671                                                 $a_xml_writer->xmlElement("mattext", NULL, $value->get_answertext());
00672                                                 $a_xml_writer->xmlEndTag("material");
00673                                                 $a_xml_writer->xmlEndTag("response_label");
00674                                         }
00675                                         $a_xml_writer->xmlEndTag("render_choice");
00676                                         $a_xml_writer->xmlEndTag("response_str");
00677                                 }
00678                                 else
00679                                 {
00680                                         // text fields
00681                                         $attrs = array(
00682                                                 "ident" => "gap_$i",
00683                                                 "rcardinality" => "Single"
00684                                         );
00685                                         $a_xml_writer->xmlStartTag("response_str", $attrs);
00686                                         $solution = $this->getSuggestedSolution($i);
00687                                         if (count($solution))
00688                                         {
00689                                                 if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $solution["internal_link"], $matches))
00690                                                 {
00691                                                         $attrs = array(
00692                                                                 "label" => "suggested_solution"
00693                                                         );
00694                                                         $a_xml_writer->xmlStartTag("material", $attrs);
00695                                                         $intlink = "il_" . IL_INST_ID . "_" . $matches[2] . "_" . $matches[3];
00696                                                         if (strcmp($matches[1], "") != 0)
00697                                                         {
00698                                                                 $intlink = $solution["internal_link"];
00699                                                         }
00700                                                         $a_xml_writer->xmlElement("mattext", NULL, $intlink);
00701                                                         $a_xml_writer->xmlEndTag("material");
00702                                                 }
00703                                         }
00704                                         $attrs = array(
00705                                                 "fibtype" => "String",
00706                                                 "prompt" => "Box",
00707                                                 "columns" => $this->getColumnSize($gap)
00708                                         );
00709                                         $a_xml_writer->xmlStartTag("render_fib", $attrs);
00710                                         $a_xml_writer->xmlEndTag("render_fib");
00711                                         $a_xml_writer->xmlEndTag("response_str");
00712                                 }
00713                         }
00714                 }
00715                 $a_xml_writer->xmlEndTag("flow");
00716                 $a_xml_writer->xmlEndTag("presentation");
00717 
00718                 // PART II: qti resprocessing
00719                 $a_xml_writer->xmlStartTag("resprocessing");
00720                 $a_xml_writer->xmlStartTag("outcomes");
00721                 $a_xml_writer->xmlStartTag("decvar");
00722                 $a_xml_writer->xmlEndTag("decvar");
00723                 $a_xml_writer->xmlEndTag("outcomes");
00724 
00725                 // add response conditions
00726                 for ($i = 0; $i < $this->get_gap_count(); $i++)
00727                 {
00728                         $gap = $this->get_gap($i);
00729                         if ($gap[0]->get_cloze_type() == CLOZE_SELECT)
00730                         {
00731                                 foreach ($gap as $index => $answer)
00732                                 {
00733                                         $attrs = array(
00734                                                 "continue" => "Yes"
00735                                         );
00736                                         $a_xml_writer->xmlStartTag("respcondition", $attrs);
00737                                         // qti conditionvar
00738                                         $a_xml_writer->xmlStartTag("conditionvar");
00739 
00740                                         if (!$answer->isStateSet())
00741                                         {
00742                                                 $a_xml_writer->xmlStartTag("not");
00743                                         }
00744 
00745                                         $attrs = array(
00746                                                 "respident" => "gap_$i"
00747                                         );
00748                                         $a_xml_writer->xmlElement("varequal", $attrs, $answer->get_answertext());
00749                                         if (!$answer->isStateSet())
00750                                         {
00751                                                 $a_xml_writer->xmlEndTag("not");
00752                                         }
00753                                         $a_xml_writer->xmlEndTag("conditionvar");
00754                                         // qti setvar
00755                                         $attrs = array(
00756                                                 "action" => "Add"
00757                                         );
00758                                         $a_xml_writer->xmlElement("setvar", $attrs, $answer->get_points());
00759                                         // qti displayfeedback
00760                                         $linkrefid = "";
00761                                         if ($answer->get_points() > 0)
00762                                         {
00763                                                 $linkrefid = "$i" . "_True";
00764                                         }
00765                                                 else
00766                                         {
00767                                                 $linkrefid = "$i" . "_False_$index";
00768                                         }
00769                                         $attrs = array(
00770                                                 "feedbacktype" => "Response",
00771                                                 "linkrefid" => $linkrefid
00772                                         );
00773                                         $a_xml_writer->xmlElement("displayfeedback", $attrs);
00774                                         $a_xml_writer->xmlEndTag("respcondition");
00775                                 }
00776                         }
00777                         else
00778                         {
00779                                 foreach ($gap as $index => $answer)
00780                                 {
00781                                         $attrs = array(
00782                                                 "continue" => "Yes"
00783                                         );
00784                                         $a_xml_writer->xmlStartTag("respcondition", $attrs);
00785                                         // qti conditionvar
00786                                         $a_xml_writer->xmlStartTag("conditionvar");
00787                                         $attrs = array(
00788                                                 "respident" => "gap_$i"
00789                                         );
00790                                         $a_xml_writer->xmlElement("varequal", $attrs, $answer->get_answertext());
00791                                         $a_xml_writer->xmlEndTag("conditionvar");
00792                                         // qti setvar
00793                                         $attrs = array(
00794                                                 "action" => "Add"
00795                                         );
00796                                         $a_xml_writer->xmlElement("setvar", $attrs, $answer->get_points());
00797                                         // qti displayfeedback
00798                                         $attrs = array(
00799                                                 "feedbacktype" => "Response",
00800                                                 "linkrefid" => "$i" . "_True_$index"
00801                                         );
00802                                         $a_xml_writer->xmlElement("displayfeedback", $attrs);
00803                                         $a_xml_writer->xmlEndTag("respcondition");
00804                                 }
00805                         }
00806                 }
00807                 $a_xml_writer->xmlEndTag("resprocessing");
00808 
00809                 // PART III: qti itemfeedback
00810                 for ($i = 0; $i < $this->get_gap_count(); $i++)
00811                 {
00812                         $gap = $this->get_gap($i);
00813                         if ($gap[0]->get_cloze_type() == CLOZE_SELECT)
00814                         {
00815                                 foreach ($gap as $index => $answer)
00816                                 {
00817                                         $linkrefid = "";
00818                                         if ($answer->isStateSet())
00819                                         {
00820                                                 $linkrefid = "$i" . "_True";
00821                                         }
00822                                                 else
00823                                         {
00824                                                 $linkrefid = "$i" . "_False_$index";
00825                                         }
00826                                         $attrs = array(
00827                                                 "ident" => $linkrefid,
00828                                                 "view" => "All"
00829                                         );
00830                                         $a_xml_writer->xmlStartTag("itemfeedback", $attrs);
00831                                         // qti flow_mat
00832                                         $a_xml_writer->xmlStartTag("flow_mat");
00833                                         $a_xml_writer->xmlStartTag("material");
00834                                         $a_xml_writer->xmlElement("mattext");
00835                                         $a_xml_writer->xmlEndTag("material");
00836                                         $a_xml_writer->xmlEndTag("flow_mat");
00837                                         $a_xml_writer->xmlEndTag("itemfeedback");
00838                                 }
00839                         }
00840                         else
00841                         {
00842                                 foreach ($gap as $index => $answer)
00843                                 {
00844                                         $linkrefid = "";
00845                                         if ($answer->isStateSet())
00846                                         {
00847                                                 $linkrefid = "$i" . "_True_$index";
00848                                         }
00849                                                 else
00850                                         {
00851                                                 $linkrefid = "$i" . "_False_$index";
00852                                         }
00853                                         $attrs = array(
00854                                                 "ident" => $linkrefid,
00855                                                 "view" => "All"
00856                                         );
00857                                         $a_xml_writer->xmlStartTag("itemfeedback", $attrs);
00858                                         // qti flow_mat
00859                                         $a_xml_writer->xmlStartTag("flow_mat");
00860                                         $a_xml_writer->xmlStartTag("material");
00861                                         $a_xml_writer->xmlElement("mattext");
00862                                         $a_xml_writer->xmlEndTag("material");
00863                                         $a_xml_writer->xmlEndTag("flow_mat");
00864                                         $a_xml_writer->xmlEndTag("itemfeedback");
00865                                 }
00866                         }
00867                 }
00868                 
00869                 $a_xml_writer->xmlEndTag("item");
00870                 $a_xml_writer->xmlEndTag("questestinterop");
00871 
00872                 $xml = $a_xml_writer->xmlDumpMem(FALSE);
00873                 if (!$a_include_header)
00874                 {
00875                         $pos = strpos($xml, "?>");
00876                         $xml = substr($xml, $pos + 2);
00877                 }
00878                 return $xml;
00879         }
00880 
00892         function set_cloze_text($cloze_text = "")
00893         {
00894                 $this->gaps = array();
00895                 $this->cloze_text =& $cloze_text;
00896                 $close = $this->createCloseTextArray();
00897                 if (count($close))
00898                 {
00899                         foreach ($close["gaps"] as $key => $value)
00900                         {
00901                                 if (strcmp(strtolower($value["params"]["type"]), "select") == 0)
00902                                 {
00903                                         $type = CLOZE_SELECT;
00904                                 }
00905                                         else
00906                                 {
00907                                         $type = CLOZE_TEXT;
00908                                 }
00909                                 if ($type == CLOZE_TEXT)
00910                                 {
00911                                         $default_state = 1;
00912                                 }
00913                                 else
00914                                 {
00915                                         $default_state = 0;
00916                                 }
00917                                 $name = $value["params"]["name"];
00918                                 if (strcmp(strtolower($value["params"]["shuffle"]), "no") == 0)
00919                                 {
00920                                         $shuffle = 0;
00921                                 }
00922                                         else
00923                                 {
00924                                         $shuffle = 1;
00925                                 }
00926                                 $answer_array = array();
00927                                 include_once "./assessment/classes/class.assAnswerCloze.php";
00928                                 foreach ($value["text"] as $index => $textvalue)
00929                                 {
00930                                         if (preg_match("/\d+/", $index))
00931                                         {
00932                                                 $textvalue = str_replace("\,", ",", $textvalue);
00933                                                 array_push($answer_array, new ASS_AnswerCloze($textvalue, 0, $index, $default_state, $type, $name, $shuffle));
00934                                         }
00935                                 }
00936                                 array_push($this->gaps, $answer_array);
00937                         }
00938                 }
00939         }
00940 
00950   function get_cloze_text() {
00951     return $this->cloze_text;
00952   }
00953 
00963   function get_start_tag() {
00964     return $this->start_tag;
00965   }
00966 
00976   function get_end_tag() {
00977     return $this->end_tag;
00978   }
00979 
00989   function set_start_tag($start_tag = "<gap>") {
00990     $this->start_tag = $start_tag;
00991   }
00992 
00993 
01003   function set_end_tag($end_tag = "</gap>") {
01004     $this->end_tag = $end_tag;
01005   }
01006 
01015   function rebuild_cloze_text() 
01016         {
01017                 $close =& $this->createCloseTextArray();
01018                 if (count($close))
01019                 {
01020                         for ($i = 0; $i < count($this->gaps); $i++)
01021                         {
01022                                 $gaptext = $this->get_gap_text_list($i);
01023                                 $textparams = preg_split("/(?<!\\\\),/", $gaptext);
01024                                 $close["gaps"][$i]["text"] = array();
01025                                 $close["gaps"][$i]["text"]["text"] = $gaptext;
01026                                 foreach ($textparams as $key => $value)
01027                                 {
01028                                         $close["gaps"][$i]["text"][$key] = $value;
01029                                 }
01030                         }
01031                 }
01032                 $this->createCloseTextFromArray($close);
01033   }
01034 
01046   function get_gap($index = 0) {
01047     if ($index < 0) return array();
01048     if (count($this->gaps) < 1) return array();
01049     if ($index >= count($this->gaps)) return array();
01050     return $this->gaps[$index];
01051   }
01052 
01062   function get_gap_count() {
01063     return count($this->gaps);
01064   }
01065 
01078   function get_gap_text_list($index = 0, $separator = ",") {
01079     if ($index < 0) return "";
01080     if (count($this->gaps) < 1) return "";
01081     if ($index >= count($this->gaps)) return "";
01082     $result = array();
01083     foreach ($this->gaps[$index] as $key => $value) {
01084                         array_push($result, str_replace(",", "\,", $value->get_answertext()));
01085     }
01086     return join($separator, $result);
01087   }
01097   function get_gap_text_count($index = 0) {
01098     if ($index < 0) return 0;
01099     if (count($this->gaps) < 1) return 0;
01100     if ($index >= count($this->gaps)) return 0;
01101     return count($this->gaps[$index]);
01102   }
01113   function delete_gap($index = 0) {
01114     if ($index < 0) return;
01115     if (count($this->gaps) < 1) return;
01116     if ($index >= count($this->gaps)) return;
01117                 $close = $this->createCloseTextArray();
01118                 unset($close["gaps"][$index]);
01119                 $this->createCloseTextFromArray($close);
01120     unset($this->gaps[$index]);
01121     $this->gaps = array_values($this->gaps);
01122   }
01123 
01132   function flush_gaps() {
01133     $this->gaps = array();
01134   }
01135 
01147   function delete_answertext_by_index($gap_index = 0, $answertext_index = 0) {
01148     if ($gap_index < 0) return;
01149     if (count($this->gaps) < 1) return;
01150     if ($gap_index >= count($this->gaps)) return;
01151     $old_text = $this->get_gap_text_list($gap_index);
01152                 if (count($this->gaps[$gap_index]) == 1) {
01153                         $this->delete_gap($gap_index);
01154                 } else {
01155                         $close = $this->createCloseTextArray();
01156                         unset($this->gaps[$gap_index][$answertext_index]);
01157       $this->gaps[$gap_index] = array_values($this->gaps[$gap_index]);
01158                         unset($close["gaps"][$gap_index]["text"][$answertext_index]);
01159                         $this->createCloseTextFromArray($close);
01160                 }
01161   }
01162 
01175   function set_answertext($index = 0, $answertext_index = 0, $answertext = "", $add_gaptext=0) 
01176         {
01177                 $answertext = str_replace("\,", ",", $answertext);
01178         if ($add_gaptext == 1)
01179                 {
01180         $arr = $this->gaps[$index][0];
01181         if (strlen($this->gaps[$index][count($this->gaps[$index])-1]->get_answertext()) != 0) 
01182                         {
01183                                 $default_state = 0;
01184                                 $default_points = 0;
01185                                 if ($arr->get_cloze_type() == CLOZE_TEXT)
01186                                 {
01187                                         $default_state = 1;
01188                                         if ($answertext_index > 0) $default_points = $this->gaps[$index][0]->get_points();
01189                                 }
01190                                 include_once "./assessment/classes/class.assAnswerCloze.php";
01191                 array_push($this->gaps[$index], new ASS_AnswerCloze($answertext, $default_points, count($this->gaps[$index]),
01192                         $default_state, $arr->get_cloze_type(),
01193                         $arr->get_name(), $arr->get_shuffle()));
01194                 $this->rebuild_cloze_text();
01195         }
01196         return;
01197     }
01198     if ($index < 0) return;
01199     if (count($this->gaps) < 1) return;
01200     if ($index >= count($this->gaps)) return;
01201     if ($answertext_index < 0) return;
01202     if (count($this->gaps[$index]) < 1) return;
01203     if ($answertext_index >= count($this->gaps[$index])) return;
01204 
01205 
01206     if (strlen($answertext) == 0) 
01207                 {
01208       // delete the answertext
01209       $this->delete_answertext($index, $this->gaps[$index][$answertext_index]->get_answertext());
01210     } 
01211                 else 
01212                 {
01213       $this->gaps[$index][$answertext_index]->set_answertext($answertext);
01214       $this->rebuild_cloze_text();
01215     }
01216   }
01217 
01226         function update_all_gap_params() {
01227                 global $lng;
01228                 $close = $this->createCloseTextArray();
01229                 for ($i = 0; $i < $this->get_gap_count(); $i++)
01230                 {
01231                         $gaptext = $this->get_gap_text_list($i);
01232                         if ($this->gaps[$i][0]->get_cloze_type() == CLOZE_TEXT)
01233                         {
01234                                 $close["gaps"][$i]["params"]["type"] = "text";
01235                                 if (array_key_exists("shuffle", $close["gaps"][$i]["params"]))
01236                                 {
01237                                         unset($close["gaps"][$i]["params"]["shuffle"]);
01238                                 }
01239                         }
01240                                 else
01241                         {
01242                                 $close["gaps"][$i]["params"]["type"] = "select";
01243                                 if ($this->gaps[$i][0]->get_shuffle() == 0)
01244                                 {
01245                                         $close["gaps"][$i]["params"]["shuffle"] = "no";
01246                                 }
01247                                         else
01248                                 {
01249                                         $close["gaps"][$i]["params"]["shuffle"] = "yes";
01250                                 }
01251                         }
01252                         $name = $this->gaps[$i][0]->get_name();
01253                         if (!$name)
01254                         {
01255                                 $name = $this->lng->txt("gap") . " " . ($i+1);
01256                         }
01257                         $close["gaps"][$i]["params"]["name"] = $name;
01258                 }
01259                 $this->createCloseTextFromArray($close);
01260         }
01261 
01272         function set_cloze_type($index, $cloze_type = CLOZE_TEXT) {
01273     if ($index < 0) return;
01274     if (count($this->gaps) < 1) return;
01275     if ($index >= count($this->gaps)) return;
01276                 $close = $this->createCloseTextArray();
01277                 foreach ($this->gaps[$index] as $key => $value) {
01278                         $this->gaps[$index][$key]->set_cloze_type($cloze_type);
01279                         $this->gaps[$index][$key]->setState(1);
01280                 }
01281                 if ($cloze_type == CLOZE_TEXT)
01282                 {
01283                         $type = "text";
01284                 }
01285                 else
01286                 {
01287                         $type = "select";
01288                 }
01289                 $close["gaps"][$index]["type"] = $type;
01290                 $this->createCloseTextFromArray($close);
01291         }
01292 
01304   function set_gap_points($index = 0, $points = 0.0) {
01305     if ($index < 0) return;
01306     if (count($this->gaps) < 1) return;
01307     if ($index >= count($this->gaps)) return;
01308     foreach ($this->gaps[$index] as $key => $value) {
01309       $this->gaps[$index][$key]->set_points($points);
01310     }
01311   }
01312 
01324   function set_gap_shuffle($index = 0, $shuffle = 1) {
01325     if ($index < 0) return;
01326     if (count($this->gaps) < 1) return;
01327     if ($index >= count($this->gaps)) return;
01328     foreach ($this->gaps[$index] as $key => $value) {
01329       $this->gaps[$index][$key]->set_shuffle($shuffle);
01330     }
01331   }
01332 
01333 
01346   function set_single_answer_points($index_gaps = 0, $index_answerobject = 0, $points = 0.0) {
01347     if ($index_gaps < 0) return;
01348     if (count($this->gaps) < 1) return;
01349     if ($index_gaps >= count($this->gaps)) return;
01350     if ($index_answerobject < 0) return;
01351     if (count($this->gaps[$index_gaps]) < 1) return;
01352     if ($index_answerobject >= count($this->gaps[$index_gaps])) return;
01353     $this->gaps[$index_gaps][$index_answerobject]->set_points($points);
01354   }
01355 
01368   function set_single_answer_state($index_gaps = 0, $index_answerobject = 0, $state = 0) {
01369     if ($index_gaps < 0) return;
01370     if (count($this->gaps) < 1) return;
01371     if ($index_gaps >= count($this->gaps)) return;
01372     if ($index_answerobject < 0) return;
01373     if (count($this->gaps[$index_gaps]) < 1) return;
01374     if ($index_answerobject >= count($this->gaps[$index_gaps])) return;
01375     $this->gaps[$index_gaps][$index_answerobject]->setState($state);
01376   }
01377         
01389         function getTextgapPoints($a_original, $a_entered, $max_points)
01390         {
01391                 $result = 0;
01392                 $gaprating = $this->getTextgapRating();
01393                 switch ($gaprating)
01394                 {
01395                         case TEXTGAP_RATING_CASEINSENSITIVE:
01396                                 if (strcmp(strtolower(utf8_decode($a_original)), strtolower(utf8_decode($a_entered))) == 0) $result = $max_points;
01397                                 break;
01398                         case TEXTGAP_RATING_CASESENSITIVE:
01399                                 if (strcmp(utf8_decode($a_original), utf8_decode($a_entered)) == 0) $result = $max_points;
01400                                 break;
01401                         case TEXTGAP_RATING_LEVENSHTEIN1:
01402                                 if (levenshtein(utf8_decode($a_original), utf8_decode($a_entered)) <= 1) $result = $max_points;
01403                                 break;
01404                         case TEXTGAP_RATING_LEVENSHTEIN2:
01405                                 if (levenshtein(utf8_decode($a_original), utf8_decode($a_entered)) <= 2) $result = $max_points;
01406                                 break;
01407                         case TEXTGAP_RATING_LEVENSHTEIN3:
01408                                 if (levenshtein(utf8_decode($a_original), utf8_decode($a_entered)) <= 3) $result = $max_points;
01409                                 break;
01410                         case TEXTGAP_RATING_LEVENSHTEIN4:
01411                                 if (levenshtein(utf8_decode($a_original), utf8_decode($a_entered)) <= 4) $result = $max_points;
01412                                 break;
01413                         case TEXTGAP_RATING_LEVENSHTEIN5:
01414                                 if (levenshtein(utf8_decode($a_original), utf8_decode($a_entered)) <= 5) $result = $max_points;
01415                                 break;
01416                 }
01417                 return $result;
01418         }
01419         
01431         function calculateReachedPoints($user_id, $test_id, $pass = NULL)
01432         {
01433                 global $ilDB;
01434                 
01435     $found_value1 = array();
01436     $found_value2 = array();
01437                 if (is_null($pass))
01438                 {
01439                         $pass = $this->getSolutionMaxPass($user_id, $test_id);
01440                 }
01441                 $query = sprintf("SELECT * FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s AND pass = %s",
01442                         $ilDB->quote($user_id . ""),
01443                         $ilDB->quote($test_id . ""),
01444                         $ilDB->quote($this->getId() . ""),
01445                         $ilDB->quote($pass . "")
01446                 );
01447     $result = $ilDB->query($query);
01448                 $user_result = array();
01449     while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) 
01450                 {
01451                         if (strcmp($data->value2, "") != 0)
01452                         {
01453                                 $user_result[$data->value1] = array(
01454                                         "gap_id" => $data->value1,
01455                                         "value" => $data->value2
01456                                 );
01457                         }
01458     }
01459     $points = 0;
01460     $counter = 0;
01461                 foreach ($user_result as $gap_id => $value) 
01462                 {
01463                         if ($this->gaps[$gap_id][0]->get_cloze_type() == CLOZE_TEXT) 
01464                         {
01465                                 $gappoints = 0;
01466                                 foreach ($this->gaps[$gap_id] as $k => $v) 
01467                                 {
01468                                         $gotpoints = $this->getTextgapPoints($v->get_answertext(), $value["value"], $v->get_points());
01469                                         if ($gotpoints > $gappoints) $gappoints = $gotpoints;
01470                                 }
01471                                 $points += $gappoints;
01472                         } 
01473                         else 
01474                         {
01475                                 if ($value["value"] >= 0)
01476                                 {
01477                                         foreach ($this->gaps[$gap_id] as $answerkey => $answer)
01478                                         {
01479                                                 if ($value["value"] == $answerkey)
01480                                                 {
01481                                                         $points += $answer->get_points();
01482                                                 }
01483                                         }
01484                                 }
01485                         }
01486     }
01487 
01488                 // check for special scoring options in test
01489                 $query = sprintf("SELECT * FROM tst_tests WHERE test_id = %s",
01490                         $ilDB->quote($test_id)
01491                 );
01492                 $result = $ilDB->query($query);
01493                 if ($result->numRows() == 1)
01494                 {
01495                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
01496                         if ($row["count_system"] == 1)
01497                         {
01498                                 if ($points != $this->getMaximumPoints())
01499                                 {
01500                                         $points = 0;
01501                                 }
01502                         }
01503                 }
01504                 else
01505                 {
01506                         $points = 0;
01507                 }
01508                 return $points;
01509         }
01510 
01520   function getReachedInformation($user_id, $test_id, $pass = NULL) 
01521         {
01522     $found_value1 = array();
01523     $found_value2 = array();
01524                 $pass = array();
01525                 if (is_null($pass))
01526                 {
01527                         $pass = $this->getSolutionMaxPass($user_id, $test_id);
01528                 }
01529                 $query = sprintf("SELECT * FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s AND pass = %s",
01530                         $this->ilias->db->quote($user_id . ""),
01531                         $this->ilias->db->quote($test_id . ""),
01532                         $this->ilias->db->quote($this->getId() . ""),
01533                         $this->ilias->db->quote($pass . "")
01534                 );
01535     $result = $this->ilias->db->query($query);
01536     while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) 
01537                 {
01538       array_push($found_value1, $data->value1);
01539       array_push($found_value2, $data->value2);
01540     }
01541     $counter = 1;
01542                 $user_result = array();
01543     foreach ($found_value1 as $key => $value) 
01544                 {
01545       if ($this->gaps[$value][0]->get_cloze_type() == CLOZE_TEXT) 
01546                         {
01547                                 $solution = array(
01548                                         "gap" => "$counter",
01549                                         "points" => 0,
01550                                         "true" => 0,
01551                                         "value" => $found_value2[$key]
01552                                 );
01553         foreach ($this->gaps[$value] as $k => $v) 
01554                                 {
01555           if (strcmp(strtolower($v->get_answertext()), strtolower($found_value2[$key])) == 0) 
01556                                         {
01557                                                 $solution = array(
01558                                                         "gap" => "$counter",
01559                                                         "points" => $v->get_points(),
01560                                                         "true" => 1,
01561                                                         "value" => $found_value2[$key]
01562                                                 );
01563           }
01564         }
01565       } 
01566                         else 
01567                         {
01568                                 $solution = array(
01569                                         "gap" => "$counter",
01570                                         "points" => 0,
01571                                         "true" => 0,
01572                                         "value" => $found_value2[$key]
01573                                 );
01574         if ($this->gaps[$value][$found_value1[$key]]->isStateSet()) 
01575                                 {
01576                                         $solution["points"] = $this->gaps[$value][$found_value1[$key]]->get_points();
01577                                         $solution["true"] = 1;
01578         }
01579       }
01580                         $counter++;
01581                         $user_result[$value] = $solution;
01582     }
01583     return $user_result;
01584   }
01585 
01594   function getMaximumPoints() {
01595     $points = 0;
01596     foreach ($this->gaps as $key => $value) {
01597       if ($value[0]->get_cloze_type() == CLOZE_TEXT) 
01598                         {
01599                                 $gap_max_points = 0;
01600         foreach ($value as $key2 => $value2) 
01601                                 {
01602                                         if ($value2->get_points() > $gap_max_points)
01603                                         {
01604                                                 $gap_max_points = $value2->get_points();
01605                                         }
01606                                 }
01607         $points += $gap_max_points;
01608       } else 
01609                         {
01610                                 $points_arr = array("set" => 0, "unset" => 0);
01611         foreach ($value as $key2 => $value2) 
01612                                 {
01613                                         if ($value2->get_points() > $points_arr["set"])
01614                                         {
01615                                                 $points_arr["set"] = $value2->get_points();
01616                                         }
01617                                 }
01618                                 $points += $points_arr["set"];
01619       }
01620     }
01621     return $points;
01622   }
01623 
01634   function saveWorkingData($test_id, $pass = NULL) 
01635         {
01636     global $ilDB;
01637                 global $ilUser;
01638     $db =& $ilDB->db;
01639 
01640                 include_once "./assessment/classes/class.ilObjTest.php";
01641                 $activepass = ilObjTest::_getPass($ilUser->id, $test_id);
01642                 
01643     $query = sprintf("DELETE FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s AND pass = %s",
01644                         $db->quote($ilUser->id),
01645                         $db->quote($test_id),
01646                         $db->quote($this->getId()),
01647                         $db->quote($activepass . "")
01648     );
01649     $result = $db->query($query);
01650 
01651                 $entered_values = 0;
01652     foreach ($_POST as $key => $value) {
01653       if (preg_match("/^gap_(\d+)/", $key, $matches)) 
01654                         { 
01655                                 $value = ilUtil::stripSlashes($value);
01656                                 if (strlen($value))
01657                                 {
01658                                         $gap = $this->get_gap($matches[1]);
01659                                         if (!(($gap[0]->get_cloze_type() == CLOZE_SELECT) && ($value == -1)))
01660                                         {
01661                                                 $query = sprintf("INSERT INTO tst_solutions (solution_id, user_fi, test_fi, question_fi, value1, value2, pass, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, NULL)",
01662                                                         $db->quote($ilUser->id),
01663                                                         $db->quote($test_id),
01664                                                         $db->quote($this->getId()),
01665                                                         $db->quote($matches[1]),
01666                                                         $db->quote($value),
01667                                                         $db->quote($activepass . "")
01668                                                 );
01669                                                 $result = $db->query($query);
01670                                                 $entered_values++;
01671                                         }
01672                                 }
01673       }
01674     }
01675                 if ($entered_values)
01676                 {
01677                         include_once ("./classes/class.ilObjAssessmentFolder.php");
01678                         if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01679                         {
01680                                 $this->logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $test_id, $this->getId());
01681                         }
01682                 }
01683                 else
01684                 {
01685                         include_once ("./classes/class.ilObjAssessmentFolder.php");
01686                         if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01687                         {
01688                                 $this->logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $test_id, $this->getId());
01689                         }
01690                 }
01691     parent::saveWorkingData($test_id, $pass);
01692                 return true;
01693   }
01694 
01695         function syncWithOriginal()
01696         {
01697                 global $ilias;
01698                 if ($this->original_id)
01699                 {
01700                         $complete = 0;
01701                         if ($this->isComplete())
01702                         {
01703                                 $complete = 1;
01704                         }
01705                         $db = & $ilias->db;
01706         
01707                         $estw_time = $this->getEstimatedWorkingTime();
01708                         $estw_time = sprintf("%02d:%02d:%02d", $estw_time['h'], $estw_time['m'], $estw_time['s']);
01709         
01710                         $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, textgap_rating = %s, complete = %s WHERE question_id = %s",
01711                                 $db->quote($this->obj_id. ""),
01712                                 $db->quote($this->title . ""),
01713                                 $db->quote($this->comment . ""),
01714                                 $db->quote($this->getMaximumPoints() . ""),
01715                                 $db->quote($this->author . ""),
01716                                 $db->quote($this->cloze_text . ""),
01717                                 $db->quote($estw_time . ""),
01718                                 $db->quote($this->shuffle . ""),
01719                                 $db->quote($this->textgap_rating . ""),
01720                                 $db->quote($complete . ""),
01721                                 $db->quote($this->original_id . "")
01722                                 );
01723                         $result = $db->query($query);
01724 
01725                         if ($result == DB_OK)
01726                         {
01727                                 // write answers
01728                                 // delete old answers
01729                                 $query = sprintf("DELETE FROM qpl_answers WHERE question_fi = %s",
01730                                         $db->quote($this->original_id)
01731                                 );
01732                                 $result = $db->query($query);
01733         
01734                                 foreach ($this->gaps as $key => $value)
01735                                 {
01736                                         foreach ($value as $answer_id => $answer_obj)
01737                                         {
01738                                                 $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)",
01739                                                         $db->quote($this->original_id . ""),
01740                                                         $db->quote($key . ""),
01741                                                         $db->quote($answer_obj->get_answertext() . ""),
01742                                                         $db->quote($answer_obj->get_points() . ""),
01743                                                         $db->quote($answer_obj->get_order() . ""),
01744                                                         $db->quote($answer_obj->get_cloze_type() . ""),
01745                                                         $db->quote($answer_obj->get_name() . ""),
01746                                                         $db->quote($answer_obj->get_shuffle() . ""),
01747                                                         $db->quote($answer_obj->getState() . "")
01748                                                         );
01749                                                 $answer_result = $db->query($query);
01750                                         }
01751                                 }
01752                         }
01753                         parent::syncWithOriginal();
01754                 }
01755         }
01756 
01765         function getQuestionType()
01766         {
01767                 return 3;
01768         }
01769         
01778         function getColumnSize($gap)
01779         {
01780                 $size = 0;
01781                 foreach ($gap as $answer)
01782                 {
01783                         $answertextsize = strlen($answer->get_answertext());
01784                         if ($answertextsize > $size) $size = $answertextsize;
01785                 }
01786                 return $size;
01787         }
01788         
01798         function getTextgapRating()
01799         {
01800                 return $this->textgap_rating;
01801         }
01802         
01812         function setTextgapRating($a_textgap_rating)
01813         {
01814                 switch ($a_textgap_rating)
01815                 {
01816                         case TEXTGAP_RATING_CASEINSENSITIVE:
01817                         case TEXTGAP_RATING_CASESENSITIVE:
01818                         case TEXTGAP_RATING_LEVENSHTEIN1:
01819                         case TEXTGAP_RATING_LEVENSHTEIN2:
01820                         case TEXTGAP_RATING_LEVENSHTEIN3:
01821                         case TEXTGAP_RATING_LEVENSHTEIN4:
01822                         case TEXTGAP_RATING_LEVENSHTEIN5:
01823                                 $this->textgap_rating = $a_textgap_rating;
01824                                 break;
01825                         default:
01826                                 $this->textgap_rating = TEXTGAP_RATING_CASEINSENSITIVE;
01827                                 break;
01828                 }
01829         }
01830 }
01831 
01832 ?>

Generated on Fri Dec 13 2013 11:57:52 for ILIAS Release_3_6_x_branch .rev 46809 by  doxygen 1.7.1