made a copy
[atutor.git] / tools / take_test.php
1 <?php
2 /****************************************************************/
3 /* ATutor                                                                                                               */
4 /****************************************************************/
5 /* Copyright (c) 2002-2008 by Greg Gay & Joel Kronenberg        */
6 /* Adaptive Technology Resource Centre / University of Toronto  */
7 /* http://atutor.ca                                                                                             */
8 /*                                                              */
9 /* This program is free software. You can redistribute it and/or*/
10 /* modify it under the terms of the GNU General Public License  */
11 /* as published by the Free Software Foundation.                                */
12 /****************************************************************/
13 // $Id$
14 define('AT_INCLUDE_PATH', '../include/');
15 require(AT_INCLUDE_PATH.'vitals.inc.php');
16 require(AT_INCLUDE_PATH.'lib/test_result_functions.inc.php');
17 require(AT_INCLUDE_PATH.'classes/testQuestions.class.php');
18
19 $tid = intval($_REQUEST['tid']);
20 if (isset($_REQUEST['gid'])) $gid = $addslashes($_REQUEST['gid']);
21
22 //make sure max attempts not reached, and still on going
23 $sql            = "SELECT *, UNIX_TIMESTAMP(start_date) AS start_date, UNIX_TIMESTAMP(end_date) AS end_date FROM ".TABLE_PREFIX."tests WHERE test_id=".$tid." AND course_id=".$_SESSION['course_id'];
24 $result= mysql_query($sql, $db);
25 $test_row = mysql_fetch_assoc($result);
26 /* check to make sure we can access this test: */
27 if (!$test_row['guests'] && ($_SESSION['enroll'] == AT_ENROLL_NO || $_SESSION['enroll'] == AT_ENROLL_ALUMNUS)) {
28         require(AT_INCLUDE_PATH.'header.inc.php');
29         $msg->printInfos('NOT_ENROLLED');
30
31         require(AT_INCLUDE_PATH.'footer.inc.php');
32         exit;
33 }
34
35 if (!$test_row['guests'] && !authenticate_test($tid)) {
36         header('Location: '.url_rewrite('tools/my_tests.php', AT_PRETTY_URL_IS_HEADER));
37         exit;
38 }
39
40 // checks one/all questions per page, and forward user to the correct one
41 if ($test_row['display']) {
42         header('Location: '.url_rewrite('tools/take_test_q.php?tid='.$tid, AT_PRETTY_URL_IS_HEADER));
43
44
45 $out_of = $test_row['out_of'];
46
47 $sql            = "SELECT COUNT(*) AS cnt FROM ".TABLE_PREFIX."tests_results WHERE status=1 AND test_id=".$tid." AND member_id='".$_SESSION['member_id']."'";
48 $takes_result= mysql_query($sql, $db);
49 $takes = mysql_fetch_assoc($takes_result);      
50
51 if ( (($test_row['start_date'] > time()) || ($test_row['end_date'] < time())) || 
52    ( ($test_row['num_takes'] != AT_TESTS_TAKE_UNLIMITED) && ($takes['cnt'] >= $test_row['num_takes']) )  ) {
53         require(AT_INCLUDE_PATH.'header.inc.php');
54         $msg->printErrors('MAX_ATTEMPTS');
55         
56         require(AT_INCLUDE_PATH.'footer.inc.php');
57         exit;
58 }
59
60 if (isset($_POST['submit'])) {
61         // insert
62         if (!isset($_POST['gid'])) {
63                 $sql    = "SELECT result_id FROM ".TABLE_PREFIX."tests_results WHERE test_id=$tid AND member_id='$_SESSION[member_id]' AND status=0";
64                 $result = mysql_query($sql, $db);
65                 $row    = mysql_fetch_assoc($result);
66                 $result_id = $row['result_id'];
67         } else {
68                 $sql    = "INSERT INTO ".TABLE_PREFIX."tests_results VALUES (NULL, $tid, '".$_POST["gid"]."', NOW(), '', 0, NOW(), 0)";
69                 $result = mysql_query($sql, $db);
70                 $result_id = mysql_insert_id($db);
71         }
72
73         $final_score     = 0;
74         $set_final_score = TRUE; // whether or not to save the final score in the results table.
75
76         $sql    = "SELECT TQA.weight, TQA.question_id, TQ.type, TQ.answer_0, TQ.answer_1, TQ.answer_2, TQ.answer_3, TQ.answer_4, TQ.answer_5, TQ.answer_6, TQ.answer_7, TQ.answer_8, TQ.answer_9 FROM ".TABLE_PREFIX."tests_questions_assoc TQA INNER JOIN ".TABLE_PREFIX."tests_questions TQ USING (question_id) WHERE TQA.test_id=$tid ORDER BY TQA.ordering, TQ.question_id";
77         $result = mysql_query($sql, $db);
78         while ($row = mysql_fetch_assoc($result)) {
79                 if (isset($_POST['answers'][$row['question_id']])) {
80                         $obj = TestQuestions::getQuestion($row['type']);
81                         $score = $obj->mark($row);
82
83                         if (!isset($_POST["gid"])) {
84                                 $sql    = "UPDATE ".TABLE_PREFIX."tests_answers SET answer='{$_POST[answers][$row[question_id]]}', score='$score' WHERE result_id=$result_id AND question_id=$row[question_id]";
85                         } else {
86                                 $sql    = "INSERT INTO ".TABLE_PREFIX."tests_answers VALUES ($result_id, $row[question_id], 0, '{$_POST[answers][$row[question_id]]}', '$score', '')";
87                         }
88                         mysql_query($sql, $db);
89
90                         // don't set final score if there is any unmarked answers and release option is set to "after all answers are marked"
91                         if (is_null($score))
92                         {
93                                 if ($test_row['result_release']==AT_RELEASE_MARKED)
94                                         $set_empty_final_score = true;
95                         }
96                         else
97                                 $final_score += $score;
98                 }
99         }
100
101         // update the final score
102         // update status to complate to fix refresh test issue.
103         if ($set_empty_final_score)
104                 $sql    = "UPDATE ".TABLE_PREFIX."tests_results SET final_score=NULL, date_taken=date_taken, status=1, end_time=NOW() WHERE result_id=$result_id";
105         else
106                 $sql    = "UPDATE ".TABLE_PREFIX."tests_results SET final_score=$final_score, date_taken=date_taken, status=1, end_time=NOW() WHERE result_id=$result_id";
107         $result = mysql_query($sql, $db);
108
109         $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
110         if (!$_SESSION['enroll'] || $test_row['result_release']==AT_RELEASE_IMMEDIATE) {
111                 header('Location: '.url_rewrite('tools/view_results.php?tid='.$tid.SEP.'rid='.$result_id, AT_PRETTY_URL_IS_HEADER));
112                 exit;
113         }
114         header('Location: '.url_rewrite('tools/my_tests.php', AT_PRETTY_URL_IS_HEADER));
115         exit;           
116 }
117
118 if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {
119         $content_base_href = 'get.php/';
120 } else {
121         $course_base_href = 'content/' . $_SESSION['course_id'] . '/';
122 }
123
124 require(AT_INCLUDE_PATH.'header.inc.php');
125
126 /* Retrieve the content_id of this test */
127 $num_questions = $test_row['num_questions'];
128 $content_id = $test_row['content_id'];
129 $anonymous = $test_row['anonymous'];
130 $instructions = $test_row['instructions'];
131 $title = $test_row['title'];
132
133 $_letters = array(_AT('A'), _AT('B'), _AT('C'), _AT('D'), _AT('E'), _AT('F'), _AT('G'), _AT('H'), _AT('I'), _AT('J'));
134
135 // first check if there's an 'in progress' test.
136 // this is the only place in the code that makes sure there is only ONE 'in progress' test going on.
137 $in_progress = false;
138 $sql = "SELECT result_id FROM ".TABLE_PREFIX."tests_results WHERE member_id='{$_SESSION['member_id']}' AND test_id=$tid AND status=0";
139
140 $result  = mysql_query($sql);
141 if ($row = mysql_fetch_assoc($result)) {
142         $result_id = $row['result_id'];
143         $in_progress = true;
144
145         // retrieve the test questions that were saved to `tests_answers`
146
147         $sql    = "SELECT R.*, A.*, Q.* FROM ".TABLE_PREFIX."tests_answers R INNER JOIN ".TABLE_PREFIX."tests_questions_assoc A USING (question_id) INNER JOIN ".TABLE_PREFIX."tests_questions Q USING (question_id) WHERE R.result_id=$result_id AND A.test_id=$tid ORDER BY Q.question_id";
148         
149 } else if ($test_row['random']) {
150         /* Retrieve 'num_questions' question_id randomly choosed from those who are related to this test_id*/
151
152         $non_required_questions = array();
153         $required_questions     = array();
154
155         $sql    = "SELECT question_id, required FROM ".TABLE_PREFIX."tests_questions_assoc WHERE test_id=$tid";
156         $result = mysql_query($sql, $db);
157         
158         while ($row = mysql_fetch_assoc($result)) {
159                 if ($row['required'] == 1) {
160                         $required_questions[] = $row['question_id'];
161                 } else {
162                         $non_required_questions[] = $row['question_id'];
163                 }
164         }
165         
166         $num_required = count($required_questions);
167         if ($num_required < max(1, $num_questions)) {
168                 shuffle($non_required_questions);
169                 $required_questions = array_merge($required_questions, array_slice($non_required_questions, 0, $num_questions - $num_required));
170         }
171
172         $random_id_string = implode(',', $required_questions);
173
174         $sql = "SELECT TQ.*, TQA.* FROM ".TABLE_PREFIX."tests_questions TQ INNER JOIN ".TABLE_PREFIX."tests_questions_assoc TQA USING (question_id) WHERE TQ.course_id=$_SESSION[course_id] AND TQA.test_id=$tid AND TQA.question_id IN ($random_id_string) ORDER BY TQ.question_id";
175 } else {
176         $sql    = "SELECT TQ.*, TQA.* FROM ".TABLE_PREFIX."tests_questions TQ INNER JOIN ".TABLE_PREFIX."tests_questions_assoc TQA USING (question_id) WHERE TQ.course_id=$_SESSION[course_id] AND TQA.test_id=$tid ORDER BY TQA.ordering, TQA.question_id";
177 }
178
179 $result = mysql_query($sql, $db);
180
181 $questions = array();
182 while ($row = mysql_fetch_assoc($result)) {
183         $questions[] = $row;
184 }
185
186 if (!$result || !$questions) {
187         echo '<p>'._AT('no_questions').'</p>';
188         require(AT_INCLUDE_PATH.'footer.inc.php');
189         exit;
190 }
191
192 // save $questions with no response, and set status to 'in progress' in test_results <---
193 if (!isset($_REQUEST['gid']) && !$in_progress) {
194         $sql    = "INSERT INTO ".TABLE_PREFIX."tests_results VALUES (NULL, $tid, '$_SESSION[member_id]', NOW(), '', 0, NOW(), 0)";
195         $result = mysql_query($sql, $db);
196         $result_id = mysql_insert_id($db);
197 }
198 ?>
199 <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
200 <input type="hidden" name="tid" value="<?php echo $tid; ?>" />
201 <?php if (isset($_REQUEST['gid'])): ?>
202 <input type="hidden" name="gid" value="<?php echo $gid; ?>" />
203 <?php endif; ?>
204
205 <div class="input-form" style="width:80%">
206         <fieldset class="group_form"><legend class="group_form"><?php echo $title ?></legend>
207
208
209         <?php if ($instructions!=''): ?>
210                 <div style="background-color: #f3f3f3; padding: 5px 10px; margin: 0px; border-top: 1px solid">
211                         <strong><?php echo _AT('instructions'); ?></strong>
212                 </div>
213                 <div class="row" style="padding-bottom: 20px"><?php echo $instructions; ?></div>
214         <?php endif; ?>
215
216         <?php if ($anonymous): ?>
217                 <div class="row"><em><strong><?php echo _AT('test_anonymous'); ?></strong></em></div>
218         <?php endif; ?>
219
220         <?php
221         foreach ($questions as $row) {
222                 if (!isset($_POST["gid"]) && !$in_progress) {
223                         $sql    = "INSERT INTO ".TABLE_PREFIX."tests_answers VALUES ($result_id, $row[question_id], $_SESSION[member_id], '', '', '')";
224                         mysql_query($sql, $db);
225                 }
226
227                 $obj = TestQuestions::getQuestion($row['type']);
228                 $obj->display($row);
229         }
230         ?>
231         <div style="background-color: #f3f3f3; padding: 5px 10px; margin: 0px; border-top: 1px solid">
232                 <strong><?php echo _AT('done'); ?>!</strong>
233         </div>
234         <div class="row buttons">
235                 <input type="submit" name="submit" value="<?php echo _AT('submit'); ?>" accesskey="s" />
236         </div>
237 </div>
238 </form>
239 <script type="text/javascript">
240 //<!--
241 function iframeSetHeight(id, height) {
242         document.getElementById("qframe" + id).style.height = (height + 20) + "px";
243 }
244 //-->
245 </script>
246 <?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>