(no commit message)
[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                         $final_score += $score;
91                 }
92         }
93
94         // update the final score
95         // update status to complate to fix refresh test issue.
96         $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";
97         $result = mysql_query($sql, $db);
98
99         $msg->addFeedback('ACTION_COMPLETED_SUCCESSFULLY');
100         if (!$_SESSION['enroll'] || $test_row['result_release']==AT_RELEASE_IMMEDIATE) {
101                 header('Location: '.url_rewrite('tools/view_results.php?tid='.$tid.SEP.'rid='.$result_id, AT_PRETTY_URL_IS_HEADER));
102                 exit;
103         }
104         header('Location: '.url_rewrite('tools/my_tests.php', AT_PRETTY_URL_IS_HEADER));
105         exit;           
106 }
107
108 if (defined('AT_FORCE_GET_FILE') && AT_FORCE_GET_FILE) {
109         $content_base_href = 'get.php/';
110 } else {
111         $course_base_href = 'content/' . $_SESSION['course_id'] . '/';
112 }
113
114 require(AT_INCLUDE_PATH.'header.inc.php');
115
116 /* Retrieve the content_id of this test */
117 $num_questions = $test_row['num_questions'];
118 $content_id = $test_row['content_id'];
119 $anonymous = $test_row['anonymous'];
120 $instructions = $test_row['instructions'];
121 $title = $test_row['title'];
122
123 $_letters = array(_AT('A'), _AT('B'), _AT('C'), _AT('D'), _AT('E'), _AT('F'), _AT('G'), _AT('H'), _AT('I'), _AT('J'));
124
125 // first check if there's an 'in progress' test.
126 // this is the only place in the code that makes sure there is only ONE 'in progress' test going on.
127 $in_progress = false;
128 $sql = "SELECT result_id FROM ".TABLE_PREFIX."tests_results WHERE member_id='{$_SESSION['member_id']}' AND test_id=$tid AND status=0";
129
130 $result  = mysql_query($sql);
131 if ($row = mysql_fetch_assoc($result)) {
132         $result_id = $row['result_id'];
133         $in_progress = true;
134
135         // retrieve the test questions that were saved to `tests_answers`
136
137         $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";
138         
139 } else if ($test_row['random']) {
140         /* Retrieve 'num_questions' question_id randomly choosed from those who are related to this test_id*/
141
142         $non_required_questions = array();
143         $required_questions     = array();
144
145         $sql    = "SELECT question_id, required FROM ".TABLE_PREFIX."tests_questions_assoc WHERE test_id=$tid";
146         $result = mysql_query($sql, $db);
147         
148         while ($row = mysql_fetch_assoc($result)) {
149                 if ($row['required'] == 1) {
150                         $required_questions[] = $row['question_id'];
151                 } else {
152                         $non_required_questions[] = $row['question_id'];
153                 }
154         }
155         
156         $num_required = count($required_questions);
157         if ($num_required < max(1, $num_questions)) {
158                 shuffle($non_required_questions);
159                 $required_questions = array_merge($required_questions, array_slice($non_required_questions, 0, $num_questions - $num_required));
160         }
161
162         $random_id_string = implode(',', $required_questions);
163
164         $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";
165 } else {
166         $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";
167 }
168
169 $result = mysql_query($sql, $db);
170
171 $questions = array();
172 while ($row = mysql_fetch_assoc($result)) {
173         $questions[] = $row;
174 }
175
176 if (!$result || !$questions) {
177         echo '<p>'._AT('no_questions').'</p>';
178         require(AT_INCLUDE_PATH.'footer.inc.php');
179         exit;
180 }
181
182 // save $questions with no response, and set status to 'in progress' in test_results <---
183 if (!isset($_REQUEST['gid']) && !$in_progress) {
184         $sql    = "INSERT INTO ".TABLE_PREFIX."tests_results VALUES (NULL, $tid, '$_SESSION[member_id]', NOW(), '', 0, NOW(), 0)";
185         $result = mysql_query($sql, $db);
186         $result_id = mysql_insert_id($db);
187 }
188 ?>
189 <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
190 <input type="hidden" name="tid" value="<?php echo $tid; ?>" />
191 <?php if (isset($_REQUEST['gid'])): ?>
192 <input type="hidden" name="gid" value="<?php echo $gid; ?>" />
193 <?php endif; ?>
194
195 <div class="input-form" style="width:80%">
196         <fieldset class="group_form"><legend class="group_form"><?php echo $title ?></legend>
197
198
199         <?php if ($instructions!=''): ?>
200                 <div style="background-color: #f3f3f3; padding: 5px 10px; margin: 0px; border-top: 1px solid">
201                         <strong><?php echo _AT('instructions'); ?></strong>
202                 </div>
203                 <div class="row" style="padding-bottom: 20px"><?php echo $instructions; ?></div>
204         <?php endif; ?>
205
206         <?php if ($anonymous): ?>
207                 <div class="row"><em><strong><?php echo _AT('test_anonymous'); ?></strong></em></div>
208         <?php endif; ?>
209
210         <?php
211         foreach ($questions as $row) {
212                 if (!isset($_POST["gid"]) && !$in_progress) {
213                         $sql    = "INSERT INTO ".TABLE_PREFIX."tests_answers VALUES ($result_id, $row[question_id], $_SESSION[member_id], '', '', '')";
214                         mysql_query($sql, $db);
215                 }
216
217                 $obj = TestQuestions::getQuestion($row['type']);
218                 $obj->display($row);
219         }
220         ?>
221         <div style="background-color: #f3f3f3; padding: 5px 10px; margin: 0px; border-top: 1px solid">
222                 <strong><?php echo _AT('done'); ?>!</strong>
223         </div>
224         <div class="row buttons">
225                 <input type="submit" name="submit" value="<?php echo _AT('submit'); ?>" accesskey="s" />
226         </div>
227 </div>
228 </form>
229 <script type="text/javascript">
230 //<!--
231 function iframeSetHeight(id, height) {
232         document.getElementById("qframe" + id).style.height = (height + 20) + "px";
233 }
234 //-->
235 </script>
236 <?php require(AT_INCLUDE_PATH.'footer.inc.php'); ?>