exercise.class.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  1. <?php // $Id: exercise.class.php 9246 2006-09-25 13:24:53Z bmol $
  2. /*
  3. ==============================================================================
  4. Dokeos - elearning and course management software
  5. Copyright (c) 2004 Dokeos S.A.
  6. Copyright (c) 2003 Ghent University (UGent)
  7. Copyright (c) 2001 Universite catholique de Louvain (UCL)
  8. Copyright (c) Olivier Brouckaert
  9. For a full list of contributors, see "credits.txt".
  10. The full license can be read in "license.txt".
  11. This program is free software; you can redistribute it and/or
  12. modify it under the terms of the GNU General Public License
  13. as published by the Free Software Foundation; either version 2
  14. of the License, or (at your option) any later version.
  15. See the GNU General Public License for more details.
  16. Contact: Dokeos, 181 rue Royale, B-1000 Brussels, Belgium, info@dokeos.com
  17. ==============================================================================
  18. */
  19. if(!class_exists('Exercise')):
  20. /**
  21. ==============================================================================
  22. CLASS EXERCISE
  23. *
  24. * This class allows to instantiate an object of type Exercise
  25. *
  26. * @author Olivier Brouckaert
  27. * @package dokeos.exercise
  28. ==============================================================================
  29. */
  30. class Exercise
  31. {
  32. var $id;
  33. var $exercise;
  34. var $description;
  35. var $sound;
  36. var $type;
  37. var $random;
  38. var $active;
  39. var $questionList; // array with the list of this exercise's questions
  40. /**
  41. * constructor of the class
  42. *
  43. * @author - Olivier Brouckaert
  44. */
  45. function Exercise()
  46. {
  47. $this->id=0;
  48. $this->exercise='';
  49. $this->description='';
  50. $this->sound='';
  51. $this->type=1;
  52. $this->random=0;
  53. $this->active=1;
  54. $this->questionList=array();
  55. }
  56. /**
  57. * reads exercise informations from the data base
  58. *
  59. * @author - Olivier Brouckaert
  60. * @param - integer $id - exercise ID
  61. * @return - boolean - true if exercise exists, otherwise false
  62. */
  63. function read($id)
  64. {
  65. global $_course;
  66. #$TBL_EXERCICE_QUESTION = $_course['dbNameGlu'].'quiz_rel_question';
  67. #$TBL_EXERCICES = $_course['dbNameGlu'].'quiz';
  68. #$TBL_QUESTIONS = $_course['dbNameGlu'].'quiz_question';
  69. #$TBL_REPONSES = $_course['dbNameGlu'].'quiz_answer';
  70. $TBL_EXERCICE_QUESTION = Database::get_course_table(QUIZ_TEST_QUESTION_TABLE);
  71. $TBL_EXERCICES = Database::get_course_table(QUIZ_TEST_TABLE);
  72. $TBL_QUESTIONS = Database::get_course_table(QUIZ_QUESTION_TABLE);
  73. #$TBL_REPONSES = Database::get_course_table(QUIZ_ANSWER_TABLE);
  74. $sql="SELECT title,description,sound,type,random,active FROM $TBL_EXERCICES WHERE id='$id'";
  75. $result=api_sql_query($sql,__FILE__,__LINE__);
  76. // if the exercise has been found
  77. if($object=mysql_fetch_object($result))
  78. {
  79. $this->id=$id;
  80. $this->exercise=$object->title;
  81. $this->description=$object->description;
  82. $this->sound=$object->sound;
  83. $this->type=$object->type;
  84. $this->random=$object->random;
  85. $this->active=$object->active;
  86. $sql="SELECT question_id,position FROM $TBL_EXERCICE_QUESTION,$TBL_QUESTIONS WHERE question_id=id AND exercice_id='$id' ORDER BY position";
  87. $result=api_sql_query($sql,__FILE__,__LINE__);
  88. // fills the array with the question ID for this exercise
  89. // the key of the array is the question position
  90. while($object=mysql_fetch_object($result))
  91. {
  92. // makes sure that the question position is unique
  93. while(isset($this->questionList[$object->position]))
  94. {
  95. $object->position++;
  96. }
  97. $this->questionList[$object->position]=$object->question_id;
  98. }
  99. return true;
  100. }
  101. // exercise not found
  102. return false;
  103. }
  104. /**
  105. * returns the exercise ID
  106. *
  107. * @author - Olivier Brouckaert
  108. * @return - integer - exercise ID
  109. */
  110. function selectId()
  111. {
  112. return $this->id;
  113. }
  114. /**
  115. * returns the exercise title
  116. *
  117. * @author - Olivier Brouckaert
  118. * @return - string - exercise title
  119. */
  120. function selectTitle()
  121. {
  122. return $this->exercise;
  123. }
  124. /**
  125. * returns the exercise description
  126. *
  127. * @author - Olivier Brouckaert
  128. * @return - string - exercise description
  129. */
  130. function selectDescription()
  131. {
  132. return $this->description;
  133. }
  134. /**
  135. * returns the exercise sound file
  136. *
  137. * @author - Olivier Brouckaert
  138. * @return - string - exercise description
  139. */
  140. function selectSound()
  141. {
  142. return $this->sound;
  143. }
  144. /**
  145. * returns the exercise type
  146. *
  147. * @author - Olivier Brouckaert
  148. * @return - integer - exercise type
  149. */
  150. function selectType()
  151. {
  152. return $this->type;
  153. }
  154. /**
  155. * tells if questions are selected randomly, and if so returns the draws
  156. *
  157. * @author - Olivier Brouckaert
  158. * @return - integer - 0 if not random, otherwise the draws
  159. */
  160. function isRandom()
  161. {
  162. return $this->random;
  163. }
  164. /**
  165. * returns the exercise status (1 = enabled ; 0 = disabled)
  166. *
  167. * @author - Olivier Brouckaert
  168. * @return - boolean - true if enabled, otherwise false
  169. */
  170. function selectStatus()
  171. {
  172. return $this->active;
  173. }
  174. /**
  175. * returns the array with the question ID list
  176. *
  177. * @author - Olivier Brouckaert
  178. * @return - array - question ID list
  179. */
  180. function selectQuestionList()
  181. {
  182. return $this->questionList;
  183. }
  184. /**
  185. * returns the number of questions in this exercise
  186. *
  187. * @author - Olivier Brouckaert
  188. * @return - integer - number of questions
  189. */
  190. function selectNbrQuestions()
  191. {
  192. return sizeof($this->questionList);
  193. }
  194. /**
  195. * selects questions randomly in the question list
  196. *
  197. * @author - Olivier Brouckaert
  198. * @return - array - if the exercise is not set to take questions randomly, returns the question list
  199. * without randomizing, otherwise, returns the list with questions selected randomly
  200. */
  201. function selectRandomList()
  202. {
  203. // if the exercise is not a random exercise, or if there are not at least 2 questions
  204. if(!$this->random || $this->selectNbrQuestions() < 2)
  205. {
  206. return $this->questionList;
  207. }
  208. // takes all questions
  209. if($this->random == -1 || $this->random > $this->selectNbrQuestions())
  210. {
  211. $draws=$this->selectNbrQuestions();
  212. }
  213. else
  214. {
  215. $draws=$this->random;
  216. }
  217. srand((double)microtime()*1000000);
  218. $randQuestionList=array();
  219. $alreadyChosed=array();
  220. // loop for the number of draws
  221. for($i=0;$i < $draws;$i++)
  222. {
  223. // selects a question randomly
  224. do
  225. {
  226. $rand=rand(0,$this->selectNbrQuestions()-1);
  227. }
  228. // if the question has already been selected, continues in the loop
  229. while(in_array($rand,$alreadyChosed));
  230. $alreadyChosed[]=$rand;
  231. $j=0;
  232. foreach($this->questionList as $key=>$val)
  233. {
  234. // if we have found the question chosed above
  235. if($j == $rand)
  236. {
  237. $randQuestionList[$key]=$val;
  238. break;
  239. }
  240. $j++;
  241. }
  242. }
  243. return $randQuestionList;
  244. }
  245. /**
  246. * returns 'true' if the question ID is in the question list
  247. *
  248. * @author - Olivier Brouckaert
  249. * @param - integer $questionId - question ID
  250. * @return - boolean - true if in the list, otherwise false
  251. */
  252. function isInList($questionId)
  253. {
  254. return in_array($questionId,$this->questionList);
  255. }
  256. /**
  257. * changes the exercise title
  258. *
  259. * @author - Olivier Brouckaert
  260. * @param - string $title - exercise title
  261. */
  262. function updateTitle($title)
  263. {
  264. $this->exercise=$title;
  265. }
  266. /**
  267. * changes the exercise description
  268. *
  269. * @author - Olivier Brouckaert
  270. * @param - string $description - exercise description
  271. */
  272. function updateDescription($description)
  273. {
  274. $this->description=$description;
  275. }
  276. /**
  277. * changes the exercise sound file
  278. *
  279. * @author - Olivier Brouckaert
  280. * @param - string $sound - exercise sound file
  281. * @param - string $delete - ask to delete the file
  282. */
  283. function updateSound($sound,$delete)
  284. {
  285. global $audioPath, $documentPath,$_course,$_uid;
  286. $TBL_DOCUMENT = Database::get_course_table(DOCUMENT_TABLE);
  287. $TBL_ITEM_PROPERTY = Database::get_course_table(ITEM_PROPERTY_TABLE);
  288. if($sound['size'] && (strstr($sound['type'],'audio') || strstr($sound['type'],'video')))
  289. {
  290. $this->sound=$sound['name'];
  291. if(@move_uploaded_file($sound['tmp_name'],$audioPath.'/'.$this->sound))
  292. {
  293. $query="SELECT 1 FROM $TBL_DOCUMENT "
  294. ." WHERE path='".str_replace($documentPath,'',$audioPath).'/'.$this->sound."'";
  295. $result=api_sql_query($query,__FILE__,__LINE__);
  296. if(!mysql_num_rows($result))
  297. {
  298. /*$query="INSERT INTO $TBL_DOCUMENT(path,filetype) VALUES "
  299. ." ('".str_replace($documentPath,'',$audioPath).'/'.$this->sound."','file')";
  300. api_sql_query($query,__FILE__,__LINE__);*/
  301. $id = add_document($_course,str_replace($documentPath,'',$audioPath).'/'.$this->sound,'file',$sound['size'],$sound['name']);
  302. //$id = Database::get_last_insert_id();
  303. //$time = time();
  304. //$time = date("Y-m-d H:i:s", $time);
  305. // insert into the item_property table, using default visibility of "visible"
  306. /*$query = "INSERT INTO $TBL_ITEM_PROPERTY "
  307. ."(tool, ref, insert_user_id,to_group_id, insert_date, lastedit_date, lastedit_type) "
  308. ." VALUES "
  309. ."('".TOOL_DOCUMENT."', $id, $_uid, 0, '$time', '$time', 'DocumentAdded' )";
  310. api_sql_query($query,__FILE__,__LINE__);*/
  311. api_item_property_update($_course, TOOL_DOCUMENT, $id, 'DocumentAdded',$_uid);
  312. item_property_update_on_folder($_course,str_replace($documentPath,'',$audioPath),$_uid);
  313. }
  314. }
  315. }
  316. elseif($delete && is_file($audioPath.'/'.$this->sound))
  317. {
  318. $this->sound='';
  319. }
  320. }
  321. /**
  322. * changes the exercise type
  323. *
  324. * @author - Olivier Brouckaert
  325. * @param - integer $type - exercise type
  326. */
  327. function updateType($type)
  328. {
  329. $this->type=$type;
  330. }
  331. /**
  332. * sets to 0 if questions are not selected randomly
  333. * if questions are selected randomly, sets the draws
  334. *
  335. * @author - Olivier Brouckaert
  336. * @param - integer $random - 0 if not random, otherwise the draws
  337. */
  338. function setRandom($random)
  339. {
  340. $this->random=$random;
  341. }
  342. /**
  343. * enables the exercise
  344. *
  345. * @author - Olivier Brouckaert
  346. */
  347. function enable()
  348. {
  349. $this->active=1;
  350. }
  351. /**
  352. * disables the exercise
  353. *
  354. * @author - Olivier Brouckaert
  355. */
  356. function disable()
  357. {
  358. $this->active=0;
  359. }
  360. /**
  361. * updates the exercise in the data base
  362. *
  363. * @author - Olivier Brouckaert
  364. */
  365. function save()
  366. {
  367. $TBL_EXERCICES = Database::get_course_table(QUIZ_TEST_TABLE);
  368. $TBL_QUESTIONS = Database::get_course_table(QUIZ_QUESTION_TABLE);
  369. $id=$this->id;
  370. $exercise=addslashes($this->exercise);
  371. $description=addslashes($this->description);
  372. $sound=addslashes($this->sound);
  373. $type=$this->type;
  374. $random=$this->random;
  375. $active=$this->active;
  376. // exercise already exists
  377. if($id)
  378. {
  379. $sql="UPDATE $TBL_EXERCICES SET title='$exercise',description='$description',sound='$sound',type='$type',random='$random',active='$active' WHERE id='$id'";
  380. api_sql_query($sql,__FILE__,__LINE__);
  381. }
  382. // creates a new exercise
  383. else
  384. {
  385. $sql="INSERT INTO $TBL_EXERCICES(title,description,sound,type,random,active) VALUES('$exercise','$description','$sound','$type','$random','$active')";
  386. api_sql_query($sql,__FILE__,__LINE__);
  387. $this->id=mysql_insert_id();
  388. }
  389. // updates the question position
  390. foreach($this->questionList as $position=>$questionId)
  391. {
  392. $sql="UPDATE $TBL_QUESTIONS SET position='$position' WHERE id='$questionId'";
  393. api_sql_query($sql,__FILE__,__LINE__);
  394. }
  395. }
  396. /**
  397. * moves a question up in the list
  398. *
  399. * @author - Olivier Brouckaert
  400. * @param - integer $id - question ID to move up
  401. */
  402. function moveUp($id)
  403. {
  404. foreach($this->questionList as $position=>$questionId)
  405. {
  406. // if question ID found
  407. if($questionId == $id)
  408. {
  409. // position of question in the array
  410. $pos1=$position;
  411. prev($this->questionList);
  412. // position of previous question in the array
  413. $pos2=key($this->questionList);
  414. // error, can't move question
  415. if(!$pos2)
  416. {
  417. return;
  418. }
  419. $id2=$this->questionList[$pos2];
  420. // exits foreach()
  421. break;
  422. }
  423. // goes to next question
  424. next($this->questionList);
  425. }
  426. // permutes questions in the array
  427. $temp=$this->questionList[$pos2];
  428. $this->questionList[$pos2]=$this->questionList[$pos1];
  429. $this->questionList[$pos1]=$temp;
  430. }
  431. /**
  432. * moves a question down in the list
  433. *
  434. * @author - Olivier Brouckaert
  435. * @param - integer $id - question ID to move down
  436. */
  437. function moveDown($id)
  438. {
  439. foreach($this->questionList as $position=>$questionId)
  440. {
  441. // if question ID found
  442. if($questionId == $id)
  443. {
  444. // position of question in the array
  445. $pos1=$position;
  446. next($this->questionList);
  447. // position of next question in the array
  448. $pos2=key($this->questionList);
  449. // error, can't move question
  450. if(!$pos2)
  451. {
  452. return;
  453. }
  454. $id2=$this->questionList[$pos2];
  455. // exits foreach()
  456. break;
  457. }
  458. // goes to next question
  459. next($this->questionList);
  460. }
  461. // permutes questions in the array
  462. $temp=$this->questionList[$pos2];
  463. $this->questionList[$pos2]=$this->questionList[$pos1];
  464. $this->questionList[$pos1]=$temp;
  465. }
  466. /**
  467. * adds a question into the question list
  468. *
  469. * @author - Olivier Brouckaert
  470. * @param - integer $questionId - question ID
  471. * @return - boolean - true if the question has been added, otherwise false
  472. */
  473. function addToList($questionId)
  474. {
  475. // checks if the question ID is not in the list
  476. if(!$this->isInList($questionId))
  477. {
  478. // selects the max position
  479. if(!$this->selectNbrQuestions())
  480. {
  481. $pos=1;
  482. }
  483. else
  484. {
  485. $pos=max(array_keys($this->questionList))+1;
  486. }
  487. $this->questionList[$pos]=$questionId;
  488. return true;
  489. }
  490. return false;
  491. }
  492. /**
  493. * removes a question from the question list
  494. *
  495. * @author - Olivier Brouckaert
  496. * @param - integer $questionId - question ID
  497. * @return - boolean - true if the question has been removed, otherwise false
  498. */
  499. function removeFromList($questionId)
  500. {
  501. // searches the position of the question ID in the list
  502. $pos=array_search($questionId,$this->questionList);
  503. // question not found
  504. if($pos === false)
  505. {
  506. return false;
  507. }
  508. else
  509. {
  510. // deletes the position from the array containing the wanted question ID
  511. unset($this->questionList[$pos]);
  512. return true;
  513. }
  514. }
  515. /**
  516. * deletes the exercise from the database
  517. * Notice : leaves the question in the data base
  518. *
  519. * @author - Olivier Brouckaert
  520. */
  521. function delete()
  522. {
  523. $TBL_EXERCICE_QUESTION = Database::get_course_table(QUIZ_TEST_QUESTION_TABLE);
  524. $TBL_EXERCICES = Database::get_course_table(QUIZ_TEST_TABLE);
  525. $id=$this->id;
  526. $sql="DELETE FROM $TBL_EXERCICE_QUESTION WHERE exercice_id='$id'";
  527. api_sql_query($sql,__FILE__,__LINE__);
  528. $sql="DELETE FROM $TBL_EXERCICES WHERE id='$id'";
  529. api_sql_query($sql,__FILE__,__LINE__);
  530. }
  531. }
  532. endif;
  533. ?>