ILIAS  release_4-4 Revision
class.assTextSubset.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
4 require_once './Modules/TestQuestionPool/classes/class.assQuestion.php';
5 require_once './Modules/Test/classes/inc.AssessmentConstants.php';
6 require_once './Modules/TestQuestionPool/interfaces/interface.ilObjQuestionScoringAdjustable.php';
7 require_once './Modules/TestQuestionPool/interfaces/interface.ilObjAnswerScoringAdjustable.php';
8 
25 {
33  var $answers;
34 
43 
52 
64  public function __construct(
65  $title = "",
66  $comment = "",
67  $author = "",
68  $owner = -1,
69  $question = ""
70  )
71  {
72  parent::__construct($title, $comment, $author, $owner, $question);
73  $this->answers = array();
74  $this->correctanswers = 0;
75  }
76 
83  function isComplete()
84  {
85  if (
86  strlen($this->title)
87  && $this->author
88  && $this->question &&
89  count($this->answers) >= $this->correctanswers
90  && $this->getMaximumPoints() > 0
91  )
92  {
93  return true;
94  }
95  return false;
96  }
97 
104  public function saveToDb($original_id = "")
105  {
106  global $ilDB;
107 
111 
112  parent::saveToDb($original_id);
113  }
114 
122  function loadFromDb($question_id)
123  {
124  global $ilDB;
125 
126  $result = $ilDB->queryF("SELECT qpl_questions.*, " . $this->getAdditionalTableName() . ".* FROM qpl_questions LEFT JOIN " . $this->getAdditionalTableName() . " ON " . $this->getAdditionalTableName() . ".question_fi = qpl_questions.question_id WHERE qpl_questions.question_id = %s",
127  array("integer"),
128  array($question_id)
129  );
130  if ($result->numRows() == 1)
131  {
132  $data = $ilDB->fetchAssoc($result);
133  $this->setId($question_id);
134  $this->setObjId($data["obj_fi"]);
135  $this->setNrOfTries($data['nr_of_tries']);
136  $this->setTitle($data["title"]);
137  $this->setComment($data["description"]);
138  $this->setOriginalId($data["original_id"]);
139  $this->setAuthor($data["author"]);
140  $this->setPoints($data["points"]);
141  $this->setOwner($data["owner"]);
142  include_once("./Services/RTE/classes/class.ilRTE.php");
143  $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc($data["question_text"], 1));
144  $this->setCorrectAnswers($data["correctanswers"]);
145  $this->setTextRating($data["textgap_rating"]);
146  $this->setEstimatedWorkingTime(substr($data["working_time"], 0, 2), substr($data["working_time"], 3, 2), substr($data["working_time"], 6, 2));
147 
148  try
149  {
150  $this->setAdditionalContentEditingMode($data['add_cont_edit_mode']);
151  }
153  {
154  }
155  }
156 
157 
158  $result = $ilDB->queryF("SELECT * FROM qpl_a_textsubset WHERE question_fi = %s ORDER BY aorder ASC",
159  array('integer'),
160  array($question_id)
161  );
162  include_once "./Modules/TestQuestionPool/classes/class.assAnswerBinaryStateImage.php";
163  if ($result->numRows() > 0)
164  {
165  while ($data = $ilDB->fetchAssoc($result))
166  {
167  array_push($this->answers, new ASS_AnswerBinaryStateImage($data["answertext"], $data["points"], $data["aorder"]));
168  }
169  }
170 
171  parent::loadFromDb($question_id);
172  }
173 
179  function addAnswer($answertext, $points, $order)
180  {
181  include_once "./Modules/TestQuestionPool/classes/class.assAnswerBinaryStateImage.php";
182  if (array_key_exists($order, $this->answers))
183  {
184  // insert answer
185  $answer = new ASS_AnswerBinaryStateImage($answertext, $points, $order);
186  $newchoices = array();
187  for ($i = 0; $i < $order; $i++)
188  {
189  array_push($newchoices, $this->answers[$i]);
190  }
191  array_push($newchoices, $answer);
192  for ($i = $order; $i < count($this->answers); $i++)
193  {
194  $changed = $this->answers[$i];
195  $changed->setOrder($i+1);
196  array_push($newchoices, $changed);
197  }
198  $this->answers = $newchoices;
199  }
200  else
201  {
202  // add answer
203  array_push($this->answers, new ASS_AnswerBinaryStateImage($answertext, $points, count($this->answers)));
204  }
205  }
206 
212  function duplicate($for_test = true, $title = "", $author = "", $owner = "", $testObjId = null)
213  {
214  if ($this->id <= 0)
215  {
216  // The question has not been saved. It cannot be duplicated
217  return;
218  }
219  // duplicate the question in database
220  $this_id = $this->getId();
221  $thisObjId = $this->getObjId();
222 
223  $clone = $this;
224  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
226  $clone->id = -1;
227 
228  if( (int)$testObjId > 0 )
229  {
230  $clone->setObjId($testObjId);
231  }
232 
233  if ($title)
234  {
235  $clone->setTitle($title);
236  }
237 
238  if ($author)
239  {
240  $clone->setAuthor($author);
241  }
242  if ($owner)
243  {
244  $clone->setOwner($owner);
245  }
246 
247  if ($for_test)
248  {
249  $clone->saveToDb($original_id);
250  }
251  else
252  {
253  $clone->saveToDb();
254  }
255 
256  // copy question page content
257  $clone->copyPageOfQuestion($this_id);
258  // copy XHTML media objects
259  $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
260 
261  $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
262 
263  return $clone->id;
264  }
265 
271  function copyObject($target_questionpool_id, $title = "")
272  {
273  if ($this->id <= 0)
274  {
275  // The question has not been saved. It cannot be duplicated
276  return;
277  }
278  // duplicate the question in database
279  $clone = $this;
280  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
282  $clone->id = -1;
283  $source_questionpool_id = $this->getObjId();
284  $clone->setObjId($target_questionpool_id);
285  if ($title)
286  {
287  $clone->setTitle($title);
288  }
289  $clone->saveToDb();
290  // copy question page content
291  $clone->copyPageOfQuestion($original_id);
292  // copy XHTML media objects
293  $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
294 
295  $clone->onCopy($source_questionpool_id, $original_id, $clone->getObjId(), $clone->getId());
296 
297  return $clone->id;
298  }
299 
300  public function createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle = "")
301  {
302  if ($this->id <= 0)
303  {
304  // The question has not been saved. It cannot be duplicated
305  return;
306  }
307 
308  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
309 
310  $sourceQuestionId = $this->id;
311  $sourceParentId = $this->getObjId();
312 
313  // duplicate the question in database
314  $clone = $this;
315  $clone->id = -1;
316 
317  $clone->setObjId($targetParentId);
318 
319  if ($targetQuestionTitle)
320  {
321  $clone->setTitle($targetQuestionTitle);
322  }
323 
324  $clone->saveToDb();
325  // copy question page content
326  $clone->copyPageOfQuestion($sourceQuestionId);
327  // copy XHTML media objects
328  $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
329 
330  $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
331 
332  return $clone->id;
333  }
334 
342  function getAnswerCount()
343  {
344  return count($this->answers);
345  }
346 
356  function getAnswer($index = 0)
357  {
358  if ($index < 0) return NULL;
359  if (count($this->answers) < 1) return NULL;
360  if ($index >= count($this->answers)) return NULL;
361 
362  return $this->answers[$index];
363  }
364 
373  function deleteAnswer($index = 0)
374  {
375  if ($index < 0) return;
376  if (count($this->answers) < 1) return;
377  if ($index >= count($this->answers)) return;
378  unset($this->answers[$index]);
379  $this->answers = array_values($this->answers);
380  for ($i = 0; $i < count($this->answers); $i++)
381  {
382  if ($this->answers[$i]->getOrder() > $index)
383  {
384  $this->answers[$i]->setOrder($i);
385  }
386  }
387  }
388 
395  function flushAnswers()
396  {
397  $this->answers = array();
398  }
399 
406  function getMaximumPoints()
407  {
408  $points = array();
409  foreach ($this->answers as $answer)
410  {
411  if ($answer->getPoints() > 0)
412  {
413  array_push($points, $answer->getPoints());
414  }
415  }
416  rsort($points, SORT_NUMERIC);
417  $maxpoints = 0;
418  for ($counter = 0; $counter < $this->getCorrectAnswers(); $counter++)
419  {
420  $maxpoints += $points[$counter];
421  }
422  return $maxpoints;
423  }
424 
432  {
433  $available_answers = array();
434  foreach ($this->answers as $answer)
435  {
436  array_push($available_answers, $answer->getAnswertext());
437  }
438  return $available_answers;
439  }
440 
451  function isAnswerCorrect($answers, $answer)
452  {
453  include_once "./Services/Utilities/classes/class.ilStr.php";
454  $result = 0;
455  $textrating = $this->getTextRating();
456  foreach ($answers as $key => $value)
457  {
458  switch ($textrating)
459  {
461  if (strcmp(ilStr::strToLower($value), ilStr::strToLower($answer)) == 0 && $this->answers[$key]->getPoints() > 0) return $key;
462  break;
464  if (strcmp($value, $answer) == 0 && $this->answers[$key]->getPoints() > 0) return $key;
465  break;
467  if (levenshtein($value, $answer) <= 1 && $this->answers[$key]->getPoints() > 0) return $key;
468  break;
470  if (levenshtein($value, $answer) <= 2 && $this->answers[$key]->getPoints() > 0) return $key;
471  break;
473  if (levenshtein($value, $answer) <= 3 && $this->answers[$key]->getPoints() > 0) return $key;
474  break;
476  if (levenshtein($value, $answer) <= 4 && $this->answers[$key]->getPoints() > 0) return $key;
477  break;
479  if (levenshtein($value, $answer) <= 5 && $this->answers[$key]->getPoints() > 0) return $key;
480  break;
481  }
482  }
483  return FALSE;
484  }
485 
493  function getTextRating()
494  {
495  return $this->text_rating;
496  }
497 
505  function setTextRating($a_text_rating)
506  {
507  switch ($a_text_rating)
508  {
516  $this->text_rating = $a_text_rating;
517  break;
518  default:
519  $this->text_rating = TEXTGAP_RATING_CASEINSENSITIVE;
520  break;
521  }
522  }
523 
534  public function calculateReachedPoints($active_id, $pass = NULL, $returndetails = FALSE)
535  {
536  if( $returndetails )
537  {
538  throw new ilTestException('return details not implemented for '.__METHOD__);
539  }
540 
541  global $ilDB;
542 
543  $available_answers =& $this->getAvailableAnswers();
544  $found_counter = 0;
545 
546  if (is_null($pass))
547  {
548  $pass = $this->getSolutionMaxPass($active_id);
549  }
550  $result = $ilDB->queryF("SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
551  array('integer','integer','integer'),
552  array($active_id, $this->getId(), $pass)
553  );
554  while ($data = $ilDB->fetchAssoc($result))
555  {
556  $enteredtext = $data["value1"];
557  $index = $this->isAnswerCorrect($available_answers, $enteredtext);
558  if ($index !== FALSE)
559  {
560  unset($available_answers[$index]);
561  $points += $this->answers[$index]->getPoints();
562  }
563  }
564 
565  return $points;
566  }
567 
574  function setCorrectAnswers($a_correct_answers)
575  {
576  $this->correctanswers = $a_correct_answers;
577  }
578 
585  function getCorrectAnswers()
586  {
587  return $this->correctanswers;
588  }
589 
598  public function saveWorkingData($active_id, $pass = NULL)
599  {
600  global $ilDB;
601  global $ilUser;
602 
603  if (is_null($pass))
604  {
605  include_once "./Modules/Test/classes/class.ilObjTest.php";
606  $pass = ilObjTest::_getPass($active_id);
607  }
608  $entered_values = 0;
609 
610  $this->getProcessLocker()->requestUserSolutionUpdateLock();
611 
612  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
613  array('integer','integer','integer'),
614  array($active_id, $this->getId(), $pass)
615  );
616  require_once 'Services/Utilities/classes/class.ilUtil.php';
617  foreach ($_POST as $key => $value)
618  {
619  if (preg_match("/^TEXTSUBSET_(\d+)/", $key, $matches))
620  {
621  if (strlen($value))
622  {
623  $value = ilUtil::secureString($value);
624  $next_id = $ilDB->nextId('tst_solutions');
625  $affectedRows = $ilDB->insert("tst_solutions", array(
626  "solution_id" => array("integer", $next_id),
627  "active_fi" => array("integer", $active_id),
628  "question_fi" => array("integer", $this->getId()),
629  "value1" => array("clob", trim($value)),
630  "value2" => array("clob", null),
631  "pass" => array("integer", $pass),
632  "tstamp" => array("integer", time())
633  ));
634  $entered_values++;
635  }
636  }
637  }
638 
639  $this->getProcessLocker()->releaseUserSolutionUpdateLock();
640 
641  if ($entered_values)
642  {
643  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
645  {
646  $this->logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
647  }
648  }
649  else
650  {
651  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
653  {
654  $this->logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
655  }
656  }
657 
658  return true;
659  }
660 
661  public function saveAdditionalQuestionDataToDb()
662  {
664  global $ilDB;
665 
666  // save additional data
667  $ilDB->manipulateF( "DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
668  array( "integer" ),
669  array( $this->getId() )
670  );
671 
672  $ilDB->manipulateF( "INSERT INTO " . $this->getAdditionalTableName(
673  ) . " (question_fi, textgap_rating, correctanswers) VALUES (%s, %s, %s)",
674  array( "integer", "text", "integer" ),
675  array(
676  $this->getId(),
677  $this->getTextRating(),
678  $this->getCorrectAnswers()
679  )
680  );
681  }
682 
683  public function saveAnswerSpecificDataToDb()
684  {
686  global $ilDB;
687  $ilDB->manipulateF( "DELETE FROM qpl_a_textsubset WHERE question_fi = %s",
688  array( 'integer' ),
689  array( $this->getId() )
690  );
691 
692  foreach ($this->answers as $key => $value)
693  {
694  $answer_obj = $this->answers[$key];
695  $next_id = $ilDB->nextId( 'qpl_a_textsubset' );
696  $ilDB->manipulateF( "INSERT INTO qpl_a_textsubset (answer_id, question_fi, answertext, points, aorder, tstamp) VALUES (%s, %s, %s, %s, %s, %s)",
697  array( 'integer', 'integer', 'text', 'float', 'integer', 'integer' ),
698  array(
699  $next_id,
700  $this->getId(),
701  $answer_obj->getAnswertext(),
702  $answer_obj->getPoints(),
703  $answer_obj->getOrder(),
704  time()
705  )
706  );
707  }
708  }
709 
718  protected function reworkWorkingData($active_id, $pass, $obligationsAnswered)
719  {
720  // nothing to rework!
721  }
722 
729  function getQuestionType()
730  {
731  return "assTextSubset";
732  }
733 
740  function &joinAnswers()
741  {
742  $join = array();
743  foreach ($this->answers as $answer)
744  {
745  if (!is_array($join[$answer->getPoints() . ""]))
746  {
747  $join[$answer->getPoints() . ""] = array();
748  }
749  array_push($join[$answer->getPoints() . ""], $answer->getAnswertext());
750  }
751  return $join;
752  }
753 
761  {
762  $maxwidth = 0;
763  foreach ($this->answers as $answer)
764  {
765  $len = strlen($answer->getAnswertext());
766  if ($len > $maxwidth) $maxwidth = $len;
767  }
768  return $maxwidth + 3;
769  }
770 
778  {
779  return "qpl_qst_textsubset";
780  }
781 
789  {
790  return "qpl_a_textsubset";
791  }
792 
798  {
799  return parent::getRTETextWithMediaObjects();
800  }
801 
814  public function setExportDetailsXLS(&$worksheet, $startrow, $active_id, $pass, &$format_title, &$format_bold)
815  {
816  include_once ("./Services/Excel/classes/class.ilExcelUtils.php");
817  $solutions = $this->getSolutionValues($active_id, $pass);
818  $worksheet->writeString($startrow, 0, ilExcelUtils::_convert_text($this->lng->txt($this->getQuestionType())), $format_title);
819  $worksheet->writeString($startrow, 1, ilExcelUtils::_convert_text($this->getTitle()), $format_title);
820  $i = 1;
821  foreach ($solutions as $solution)
822  {
823  $worksheet->write($startrow + $i, 0, ilExcelUtils::_convert_text($solution["value1"]));
824  $i++;
825  }
826  return $startrow + $i + 1;
827  }
828 
829  public function getAnswers()
830  {
831  return $this->answers;
832  }
833 
837  public function toJSON()
838  {
839  include_once("./Services/RTE/classes/class.ilRTE.php");
840  $result = array();
841  $result['id'] = (int) $this->getId();
842  $result['type'] = (string) $this->getQuestionType();
843  $result['title'] = (string) $this->getTitle();
844  $result['question'] = $this->formatSAQuestion($this->getQuestion());
845  $result['nr_of_tries'] = (int) $this->getNrOfTries();
846  $result['matching_method'] = (string) $this->getTextRating();
847  $result['feedback'] = array(
848  "onenotcorrect" => $this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), false),
849  "allcorrect" => $this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), true)
850  );
851 
852  $answers = array();
853  foreach ($this->getAnswers() as $key => $answer_obj)
854  {
855  array_push($answers, array(
856  "answertext" => (string) $answer_obj->getAnswertext(),
857  "points" => (float)$answer_obj->getPoints(),
858  "order" => (int)$answer_obj->getOrder()
859  ));
860  }
861  $result['correct_answers'] = $answers;
862 
863  $answers = array();
864  for($loop = 1; $loop <= (int) $this->getCorrectAnswers(); $loop++)
865  {
866  array_push($answers, array(
867  "answernr" => $loop
868  ));
869  }
870  $result['answers'] = $answers;
871 
872  $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
873  $result['mobs'] = $mobs;
874 
875  return json_encode($result);
876  }
877 }
878 
879 ?>
addAnswer($answertext, $points, $order)
Adds an answer to the question.
getId()
Gets the id of the assQuestion object.
static _getOriginalId($question_id)
Returns the original id of a question.
formatSAQuestion($a_q)
Format self assessment question.
getCorrectAnswers()
Returns the number of correct answers needed to solve the question.
const TEXTGAP_RATING_LEVENSHTEIN5
$_POST['username']
Definition: cron.php:12
flushAnswers()
Deletes all answers.
$result
saveAdditionalQuestionDataToDb()
Saves a record to the question types additional data table.
setExportDetailsXLS(&$worksheet, $startrow, $active_id, $pass, &$format_title, &$format_bold)
Creates an Excel worksheet for the detailed cumulated results of this question.
getPoints()
Returns the maximum available points for the question.
const TEXTGAP_RATING_LEVENSHTEIN2
const TEXTGAP_RATING_LEVENSHTEIN1
& getSolutionValues($active_id, $pass=NULL)
Loads solutions of a given user from the database an returns it.
Abstract basic class which is to be extended by the concrete assessment question type classes...
_getPass($active_id)
Retrieves the actual pass of a given user for a given test.
Class for answers with a binary state indicator.
_convert_text($a_text, $a_target="has been removed")
copyObject($target_questionpool_id, $title="")
Copies an assTextSubset object.
& joinAnswers()
Returns the answers of the question as a comma separated string.
getTextRating()
Returns the rating option for text comparisons.
setTextRating($a_text_rating)
Sets the rating option for text comparisons.
getMaximumPoints()
Returns the maximum points, a learner can reach answering the question.
toJSON()
Returns a JSON representation of the question.
setId($id=-1)
Sets the id of the assQuestion object.
getAnswerTableName()
Returns the name of the answer table in the database.
getSolutionMaxPass($active_id)
Returns the maximum pass a users question solution.
Class for TextSubset questions.
setEstimatedWorkingTime($hour=0, $min=0, $sec=0)
Sets the estimated working time of a question.
static strToLower($a_string)
Definition: class.ilStr.php:91
isComplete()
Returns true, if a TextSubset question is complete for use.
setNrOfTries($a_nr_of_tries)
_enabledAssessmentLogging()
check wether assessment logging is enabled or not
setAdditionalContentEditingMode($additinalContentEditingMode)
setter for additional content editing mode for this question
getObjId()
Get the object id of the container object.
getRTETextWithMediaObjects()
Collects all text in the question which could contain media objects which were created with the Rich ...
getQuestionType()
Returns the question type of the question.
Base Exception for all Exceptions relating to Modules/Test.
__construct( $title="", $comment="", $author="", $owner=-1, $question="")
assTextSubset constructor
$mobs
fetchAssoc($a_set)
Fetch row as associative array from result set.
setAuthor($author="")
Sets the authors name of the assQuestion object.
saveToDb($original_id="")
Saves a assTextSubset object to a database.
const TEXTGAP_RATING_LEVENSHTEIN3
loadFromDb($question_id)
Loads a assTextSubset object from a database.
createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle="")
& getAvailableAnswers()
Returns the available answers for the question.
setCorrectAnswers($a_correct_answers)
Sets the number of correct answers needed to solve the question.
const TEXTGAP_RATING_CASESENSITIVE
Interface ilObjAnswerScoringAdjustable.
getQuestion()
Gets the question string of the question object.
getAnswerCount()
Returns the number of answers.
getAdditionalTableName()
Returns the name of the additional question data table in the database.
_getLogLanguage()
retrieve the log language for assessment logging
_getMobsOfObject($a_type, $a_id, $a_usage_hist_nr=0, $a_lang="-")
get mobs of object
saveAnswerSpecificDataToDb()
Saves the answer specific records into a question types answer table.
setPoints($a_points)
Sets the maximum available points for the question.
saveQuestionDataToDb($original_id="")
static _replaceMediaObjectImageSrc($a_text, $a_direction=0)
replaces image source from mob image urls with the mob id or replaces mob id with the correct image s...
calculateReachedPoints($active_id, $pass=NULL, $returndetails=FALSE)
Returns the points, a learner has reached answering the question.
getAnswer($index=0)
Returns an answer with a given index.
while($lm_rec=$ilDB->fetchAssoc($lm_set)) $data
global $ilUser
Definition: imgupload.php:15
setQuestion($question="")
Sets the question string of the question object.
Interface ilObjQuestionScoringAdjustable.
reworkWorkingData($active_id, $pass, $obligationsAnswered)
Reworks the allready saved working data if neccessary.
const TEXTGAP_RATING_LEVENSHTEIN4
setOriginalId($original_id)
static secureString($a_str, $a_strip_html=true, $a_allow="")
Remove unsecure tags.
logAction($logtext="", $active_id="", $question_id="")
Logs an action into the Test&Assessment log.
getTitle()
Gets the title string of the assQuestion object.
deleteAnswer($index=0)
Deletes an answer with a given index.
getMaxTextboxWidth()
Returns the maximum width needed for the answer textboxes.
duplicate($for_test=true, $title="", $author="", $owner="", $testObjId=null)
Duplicates an assTextSubsetQuestion.
setTitle($title="")
Sets the title string of the assQuestion object.
setObjId($obj_id=0)
Set the object id of the container object.
setComment($comment="")
Sets the comment string of the assQuestion object.
isAnswerCorrect($answers, $answer)
Returns the index of the found answer, if the given answer is in the set of correct answers and match...
saveWorkingData($active_id, $pass=NULL)
Saves the learners input of the question to the database.
setOwner($owner="")
Sets the creator/owner ID of the assQuestion object.
const TEXTGAP_RATING_CASEINSENSITIVE