Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

make compatible with PHP 5.1.2 by removing variable assignments in ca…

…lls to functions e.g. myfunction($a=1); Micro-incremented version number to 2.1.15
  • Loading branch information...
commit c20b62380495dfa39a82fcfd8a9e36a12cc1dee5 1 parent 475e9de
gbateson authored
4 mod/hotpot/README.TXT
... ... @@ -1,10 +1,10 @@
1   -This is v2.1.14 of the HotPot module
  1 +This is v2.1.15 of the HotPot module
2 2
3 3 This module allows teachers to administer Hot Potatoes and TexToys quizzes via Moodle.
4 4 It has been tested on:
5 5 - Hot Potatoes 6
6 6 - Moodle 1.1 thru 1.6
7   - - PHP 4.1 thru 5.0
  7 + - PHP 4.1 thru 5.1.2
8 8 - MySQL and PostgreSQL databases
9 9
10 10 This module may be distributed under the terms of the General Public License
66 mod/hotpot/lib.php
@@ -166,23 +166,23 @@
166 166
167 167
168 168 // possible return values:
169   -// false:
170   -// display moderr.html (if exists) OR "Could not update" and return to couse view
171   -// string:
172   -// display as error message and return to course view
  169 +// false:
  170 +// display moderr.html (if exists) OR "Could not update" and return to couse view
  171 +// string:
  172 +// display as error message and return to course view
173 173 // true (or non-zero number):
174   -// continue to $hp->redirect (if set) OR hotpot/view.php (to displsay quiz)
  174 +// continue to $hp->redirect (if set) OR hotpot/view.php (to displsay quiz)
175 175
176 176 // $hp is an object containing the values of the form in mod.html
177 177 // i.e. all the fields in the 'hotpot' table, plus the following:
178   -// $hp->course : an id in the 'course' table
179   -// $hp->coursemodule : an id in the 'course_modules' table
180   -// $hp->section : an id in the 'course_sections' table
181   -// $hp->module : an id in the 'modules' table
182   -// $hp->modulename : always 'hotpot'
183   -// $hp->instance : an id in the 'hotpot' table
184   -// $hp->mode : 'add' or 'update'
185   -// $hp->sesskey : unique string required for Moodle's session management
  178 +// $hp->course : an id in the 'course' table
  179 +// $hp->coursemodule : an id in the 'course_modules' table
  180 +// $hp->section : an id in the 'course_sections' table
  181 +// $hp->module : an id in the 'modules' table
  182 +// $hp->modulename : always 'hotpot'
  183 +// $hp->instance : an id in the 'hotpot' table
  184 +// $hp->mode : 'add' or 'update'
  185 +// $hp->sesskey : unique string required for Moodle's session management
186 186
187 187 function hotpot_add_instance(&$hp) {
188 188 if (hotpot_set_form_values($hp)) {
@@ -1255,9 +1255,9 @@ function hotpot_xml_tree($str, $xml_root='') {
1255 1255 if (empty($str)) {
1256 1256 $this->xml = array();
1257 1257 } else {
1258   - if (empty($CFG->unicodedb)) {
1259   - $str = utf8_encode($str);
1260   - }
  1258 + if (empty($CFG->unicodedb)) {
  1259 + $str = utf8_encode($str);
  1260 + }
1261 1261 $this->xml = xmlize($str, 0);
1262 1262 }
1263 1263 $this->xml_root = $xml_root;
@@ -1268,9 +1268,9 @@ function xml_value($tags, $more_tags="[0]['#']") {
1268 1268 eval('$value = &$this->xml'.$this->xml_root.$tags.$more_tags.';');
1269 1269
1270 1270 if (is_string($value)) {
1271   - if (empty($CFG->unicodedb)) {
1272   - $value = utf8_decode($value);
1273   - }
  1271 + if (empty($CFG->unicodedb)) {
  1272 + $value = utf8_decode($value);
  1273 + }
1274 1274
1275 1275 // decode angle brackets
1276 1276 $value = strtr($value, array('&#x003C;'=>'<', '&#x003E;'=>'>', '&#x0026;'=>'&'));
@@ -1296,7 +1296,7 @@ function xml_value($tags, $more_tags="[0]['#']") {
1296 1296 // encode unicode characters as HTML entities
1297 1297 // (in particular, accented charaters that have not been encoded by HP)
1298 1298
1299   - // unicode characetsr can be detected by checking the hex value of a character
  1299 + // unicode characters can be detected by checking the hex value of a character
1300 1300 // 00 - 7F : ascii char (roman alphabet + punctuation)
1301 1301 // 80 - BF : byte 2, 3 or 4 of a unicode char
1302 1302 // C0 - DF : 1st byte of 2-byte char
@@ -1306,20 +1306,6 @@ function xml_value($tags, $more_tags="[0]['#']") {
1306 1306 // 80 - FF : single-byte, non-ascii char
1307 1307 $search = '#('.'[\xc0-\xdf][\x80-\xbf]'.'|'.'[\xe0-\xef][\x80-\xbf]{2}'.'|'.'[\xf0-\xff][\x80-\xbf]{3}'.'|'.'[\x80-\xff]'.')#se';
1308 1308 $value = preg_replace($search, "hotpot_utf8_to_html_entity('\\1')", $value);
1309   -
1310   - // NOTICE
1311   - // ======
1312   - // the following lines have been removed because
1313   - // the final "preg_replace" takes several SECONDS to run
1314   -
1315   - // encode any orphaned angle brackets back to html entities
1316   - //if (empty($this->tag_pattern)) {
1317   - // $q = "'"; // single quote
1318   - // $qq = '"'; // double quote
1319   - // $this->tag_pattern = '<(([^>'.$q.$qq.']*)|('."{$q}[^$q]*$q".')|('."{$qq}[^$qq]*$qq".'))*>';
1320   - //}
1321   - //$value = preg_replace('/<([^>]*'.$this->tag_pattern.')/', '&lt;$1', $value);
1322   - //$value = preg_replace('/('.$this->tag_pattern.'[^<]*)>/', '$1&gt;', $value);
1323 1309 }
1324 1310 return $value;
1325 1311 }
@@ -1389,9 +1375,9 @@ function hotpot_xml_quiz(&$obj, $read_file=true, $parse_xml=true, $convert_urls=
1389 1375 $this->create_html = $create_html;
1390 1376
1391 1377 // extract fields from $obj
1392   - // course : the course id
1393   - // reference : the filename within the files folder
1394   - // location : "site" files folder or "course" files folder
  1378 + // course : the course id
  1379 + // reference : the filename within the files folder
  1380 + // location : "site" files folder or "course" files folder
1395 1381 // navigation : type of navigation required in quiz
1396 1382 // forceplugins : force Moodle compatible media players
1397 1383 $this->course = $this->obj_value($obj, 'course');
@@ -1664,10 +1650,10 @@ function adjust_media_urls() {
1664 1650 $filepath = "$Q\.($filetype)";
1665 1651
1666 1652 // pattern to match <param> tags which contain the file path
1667   - // wmp : url
  1653 + // wmp : url
1668 1654 // quicktime : src
1669 1655 // realplayer : src
1670   - // flash : movie (doesn't need replacing)
  1656 + // flash : movie (doesn't need replacing)
1671 1657 $param_url = "/<param$s{$n}name=$q(src|url)$q$s{$n}value=$q($filepath)$q$n>/is";
1672 1658
1673 1659 // pattern to match <a> tags which link to multimedia files (not swf)
@@ -2176,7 +2162,7 @@ function html_entity_decode($str) {
2176 2162
2177 2163 // required for Moodle 1.x
2178 2164 if (!isset($CFG->pixpath)) {
2179   - $CFG->pixpath = "$CFG->wwwroot/pix";
  2165 + $CFG->pixpath = "$CFG->wwwroot/pix";
2180 2166 }
2181 2167
2182 2168 if (!defined('PARAM_RAW')) define('PARAM_RAW', 0x0000);
1,079 mod/hotpot/report/click/report.php
... ... @@ -1,539 +1,540 @@
1   -<?php // $Id$
2   -/// Overview report just displays a big table of all the attempts
3   -class hotpot_report extends hotpot_default_report {
4   - function display(&$hotpot, &$cm, &$course, &$users, &$attempts, &$questions, &$options) {
5   - global $CFG;
6   - // create the table
7   - $this->create_clickreport_table($hotpot, $cm, $course, $users, $attempts, $questions, $options, $tables=array());
8   - // print the table
9   - $this->print_report($course, $hotpot, $tables, $options);
10   - return true;
11   - }
12   - function create_clickreport_table(&$hotpot, &$cm, &$course, &$users, &$attempts, &$questions, &$options, &$tables) {
13   - global $CFG;
14   - $is_html = ($options['reportformat']=='htm');
15   - // time and date format strings // date format strings
16   - $strftimetime = '%H:%M:%S';
17   - $strftimedate = get_string('strftimedate');
18   - // get the current time and max execution time
19   - $start_report_time = microtime();
20   - $max_execution_time = ini_get('max_execution_time');
21   - $correct = get_string('reportcorrectsymbol', 'hotpot');
22   - $wrong = get_string('reportwrongsymbol', 'hotpot');
23   - $nottried = get_string('reportnottriedsymbol', 'hotpot');
24   - // shortcuts for font tags
25   - $blank = $is_html ? '&nbsp;' : "";
26   - // store question count
27   - $questioncount = count($questions);
28   - // array to map columns onto question ids ($col => $id)
29   - $questionids = array_keys($questions);
30   - // store exercise type
31   - $exercisetype = $this->get_exercisetype($questions, $questionids, $blank);
32   - // initialize details ('events' must go last)
33   - $details = array('checks', 'status', 'answers', 'changes', 'hints', 'clues', 'events');
34   - // initialize $table
35   - unset($table);
36   - $table->border = 1;
37   - $table->width = '100%';
38   - // initialize legend, if necessary
39   - if (!empty($options['reportshowlegend'])) {
40   - $table->legend = array();
41   - }
42   - // start $table headings
43   - $this->set_head($options, $table, 'exercise');
44   - $this->set_head($options, $table, 'user');
45   - $this->set_head($options, $table, 'attempt');
46   - $this->set_head($options, $table, 'click');
47   - // store clicktype column number
48   - $clicktype_col = count($table->head)-1;
49   - // finish $table headings
50   - $this->set_head($options, $table, 'details', $exercisetype, $details, $questioncount);
51   - $this->set_head($options, $table, 'totals', $exercisetype);
52   - // set align and wrap
53   - $this->set_align_and_wrap($table);
54   - // is link to review allowed?
55   - $allow_review = ($is_html && (isteacher($course->id) || $hotpot->review));
56   - // initialize array of data values
57   - $this->data = array();
58   - // set exercise data values
59   - $this->set_data_exercise($cm, $course, $hotpot, $questions, $questionids, $questioncount, $blank);
60   - // add details of users' responses
61   - foreach ($users as $user) {
62   - $this->set_data_user($options, $course, $user);
63   - unset($clickreportid);
64   - foreach ($user->attempts as $attempt) {
65   - // initialize totals for
66   - $click = array(
67   - 'qnumber' => array(),
68   - 'correct' => array(),
69   - 'wrong' => array(),
70   - 'answers' => array(),
71   - 'hints' => array(),
72   - 'clues' => array(),
73   - 'changes' => array(),
74   - 'checks' => array(),
75   - 'events' => array(),
76   - 'score' => array(),
77   - 'weighting' => array()
78   - );
79   - $clicktypes = array();
80   - // is the start of a new attempt?
81   - // (clicks in the same attempt have the same clickreportid)
82   - if (!isset($clickreportid) || $clickreportid != $attempt->clickreportid) {
83   - $clickcount = 1;
84   - $clickreportid = $attempt->clickreportid;
85   - // initialize totals for all clicks in this attempt
86   - $clicks = $click; // $click has just been initialized
87   - $this->set_data_attempt($attempt, $strftimedate, $strftimetime, $blank);
88   - }
89   - $cells = array();
90   - $this->set_data($cells, 'exercise');
91   - $this->set_data($cells, 'user');
92   - $this->set_data($cells, 'attempt');
93   - // get responses to questions in this attempt
94   - foreach ($attempt->responses as $response) {
95   - // set $q(uestion number)
96   - $q = array_search($response->question, $questionids);
97   - $click['qnumber'][$q] = true;
98   - // was this question answered correctly?
99   - if ($answer = hotpot_strings($response->correct)) {
100   - // mark the question as correctly answered
101   - if (empty($clicks['correct'][$q])) {
102   - $click['correct'][$q] = true;
103   - $clicks['correct'][$q] = true;
104   - }
105   - // unset 'wrong' flags, if necessary
106   - if (isset($click['wrong'][$q])) {
107   - unset($click['wrong'][$q]);
108   - }
109   - if (isset($clicks['wrong'][$q])) {
110   - unset($clicks['wrong'][$q]);
111   - }
112   - // otherwise, was the question answered wrongly?
113   - } else if ($answer = hotpot_strings($response->wrong)) {
114   - // mark the question as wrongly answered
115   - $click['wrong'][$q] = true;
116   - $clicks['wrong'][$q] = true;
117   - } else { // not correct or wrong (curious?!)
118   - unset($answer);
119   - }
120   - if (!empty($click['correct'][$q]) || !empty($click['wrong'][$q])) {
121   - $click['score'][$q] = $response->score;
122   - $clicks['score'][$q] = $response->score;
123   - $weighting = isset($response->weighting) ? $response->weighting : 100;
124   - $click['weighting'][$q] = $weighting;
125   - $clicks['weighting'][$q] =$weighting;
126   - }
127   - foreach($details as $detail) {
128   - switch ($detail) {
129   - case 'answers':
130   - if (isset($answer) && is_string($answer) && !empty($answer)) {
131   - $click[$detail][$q] = $answer;
132   - }
133   - break;
134   - case 'hints':
135   - case 'clues':
136   - case 'checks':
137   - if (isset($response->$detail) && is_numeric($response->$detail) && $response->$detail>0) {
138   - if (!isset($click[$detail][$q]) || $click[$detail][$q] < $response->$detail) {
139   - $click[$detail][$q] = $response->$detail;
140   - }
141   - }
142   - break;
143   - }
144   - } // end foreach $detail
145   - } // end foreach $response
146   - $click['types'] = array();
147   - $this->data['details'] = array();
148   - foreach($details as $detail) {
149   - for ($q=0; $q<$questioncount; $q++) {
150   - switch ($detail) {
151   - case 'status':
152   - if (isset($clicks['correct'][$q])) {
153   - $this->data['details'][] = $correct;
154   - } else if (isset($clicks['wrong'][$q])) {
155   - $this->data['details'][] = $wrong;
156   - } else if (isset($click['qnumber'][$q])) {
157   - $this->data['details'][] = $nottried;
158   - } else { // this question did not appear in this attempt
159   - $this->data['details'][] = $blank;
160   - }
161   - break;
162   - case 'answers':
163   - case 'hints':
164   - case 'clues':
165   - case 'checks':
166   - if (!isset($clicks[$detail][$q])) {
167   - if (!isset($click[$detail][$q])) {
168   - $this->data['details'][] = $blank;
169   - } else {
170   - $clicks[$detail][$q] = $click[$detail][$q];
171   - if ($detail=='answers') {
172   - $this->set_legend($table, $q, $click[$detail][$q], $questions[$questionids[$q]]);
173   - }
174   - $this->data['details'][] = $click[$detail][$q];
175   - $this->update_event_count($click, $detail, $q);
176   - }
177   - } else {
178   - if (!isset($click[$detail][$q])) {
179   - $this->data['details'][] = $blank;
180   - } else {
181   - $difference = '';
182   - if ($detail=='answers') {
183   - if ($click[$detail][$q] != $clicks[$detail][$q]) {
184   - $pattern = '/^'.preg_quote($clicks[$detail][$q], '/').',/';
185   - $difference = preg_replace($pattern, '', $click[$detail][$q], 1);
186   - }
187   - } else { // hints, clues, checks
188   - if ($click[$detail][$q] > $clicks[$detail][$q]) {
189   - $difference = $click[$detail][$q] - $clicks[$detail][$q];
190   - }
191   - }
192   - if ($difference) {
193   - $clicks[$detail][$q] = $click[$detail][$q];
194   - $click[$detail][$q] = $difference;
195   - if ($detail=='answers') {
196   - $this->set_legend($table, $q, $difference, $questions[$questionids[$q]]);
197   - }
198   - $this->data['details'][] = $difference;
199   - $this->update_event_count($click, $detail, $q);
200   - } else {
201   - unset($click[$detail][$q]);
202   - $this->data['details'][] = $blank;
203   - }
204   - }
205   - }
206   - break;
207   - case 'changes':
208   - case 'events':
209   - if (empty($click[$detail][$q])) {
210   - $this->data['details'][] = $blank;
211   - } else {
212   - $this->data['details'][] = $click[$detail][$q];
213   - }
214   - break;
215   - default:
216   - // do nothing
217   - break;
218   - } // end switch
219   - } // for $q
220   - } // foreach $detail
221   - // set data cell values for
222   - $this->set_data_click(
223   - $allow_review ? '<a href="review.php?hp='.$hotpot->id.'&attempt='.$attempt->id.'">'.$clickcount.'</a>' : $clickcount,
224   - trim(userdate($attempt->timefinish, $strftimetime)),
225   - $exercisetype,
226   - $click
227   - );
228   - $this->set_data($cells, 'click');
229   - $this->set_data($cells, 'details');
230   - $this->set_data_totals($click, $clicks, $questioncount, $blank, $attempt);
231   - $this->set_data($cells, 'totals');
232   - $table->data[] = $cells;
233   - $clickcount++;
234   - } // end foreach $attempt
235   - // insert 'tabledivider' between users
236   - $table->data[] = 'hr';
237   - } // end foreach $user
238   - // remove final 'hr' from data rows
239   - array_pop($table->data);
240   - if ($is_html && $CFG->hotpot_showtimes) {
241   - $count = count($users);
242   - $duration = sprintf("%0.3f", microtime_diff($start_report_time, microtime()));
243   - print "$count users processed in $duration seconds (".sprintf("%0.3f", $duration/$count).' secs/user)<hr size="1" noshade="noshade" />'."\n";
244   - }
245   - $tables[] = &$table;
246   - $this->create_legend_table($tables, $table);
247   - } // end function
248   - function get_exercisetype(&$questions, &$questionids, &$blank) {
249   - if (empty($questions)) {
250   - $type = $blank;
251   - } else {
252   - switch ($questions[$questionids[0]]->type) {
253   - case HOTPOT_JCB:
254   - $type = "JCB";
255   - break;
256   - case HOTPOT_JCLOZE :
257   - $type = "JCloze";
258   - break;
259   - case HOTPOT_JCROSS :
260   - $type = "JCross";
261   - break;
262   - case HOTPOT_JMATCH :
263   - $type = "JMatch";
264   - break;
265   - case HOTPOT_JMIX :
266   - $type = "JMix";
267   - break;
268   - case HOTPOT_JQUIZ :
269   - $type = "JQuiz";
270   - break;
271   - case HOTPOT_TEXTOYS_RHUBARB :
272   - $type = "Rhubarb";
273   - break;
274   - case HOTPOT_TEXTOYS_SEQUITUR :
275   - $type = "Sequitur";
276   - break;
277   - default:
278   - $type = $blank;
279   - }
280   - }
281   - return $type;
282   - }
283   - function set_head(&$options, &$table, $zone, $exercisetype='', $details=array(), $questioncount=0) {
284   - if (empty($table->head)) {
285   - $table->head = array();
286   - }
287   - switch ($zone) {
288   - case 'exercise':
289   - array_push($table->head,
290   - get_string('reportcoursename', 'hotpot'),
291   - get_string('reportsectionnumber', 'hotpot'),
292   - get_string('reportexercisenumber', 'hotpot'),
293   - get_string('reportexercisename', 'hotpot'),
294   - get_string('reportexercisetype', 'hotpot'),
295   - get_string('reportnumberofquestions', 'hotpot')
296   - );
297   - break;
298   - case 'user':
299   - array_push($table->head,
300   - get_string('reportstudentid', 'hotpot'),
301   - get_string('reportlogindate', 'hotpot'),
302   - get_string('reportlogintime', 'hotpot'),
303   - get_string('reportlogofftime', 'hotpot')
304   - );
305   - break;
306   - case 'attempt':
307   - array_push($table->head,
308   - get_string('reportattemptnumber', 'hotpot'),
309   - get_string('reportattemptstart', 'hotpot'),
310   - get_string('reportattemptfinish', 'hotpot')
311   - );
312   - break;
313   - case 'click':
314   - array_push($table->head,
315   - get_string('reportclicknumber', 'hotpot'),
316   - get_string('reportclicktime', 'hotpot'),
317   - get_string('reportclicktype', 'hotpot')
318   - );
319   - break;
320   - case 'details':
321   - foreach($details as $detail) {
322   - if ($exercisetype=='JQuiz' && $detail=='clues') {
323   - $detail = 'showanswer';
324   - }
325   - $detail = get_string("report$detail", 'hotpot');
326   - for ($i=0; $i<$questioncount; $i++) {
327   - $str = get_string('questionshort', 'hotpot', $i+1);
328   - if ($i==0 || $options['reportformat']!='htm') {
329   - $str = "$detail $str";
330   - }
331   - $table->head[] = $str;
332   - }
333   - }
334   - break;
335   - case 'totals':
336   - $reportpercentscore =get_string('reportpercentscore', 'hotpot');
337   - if (!function_exists('clean_getstring_data')) { // Moodle 1.4 (and less)
338   - $reportpercentscore = str_replace('%', '%%', $reportpercentscore);
339   - }
340   - array_push($table->head,
341   - get_string('reportthisclick', 'hotpot', get_string('reportquestionstried', 'hotpot')),
342   - get_string('reportsofar', 'hotpot', get_string('reportquestionstried', 'hotpot')),
343   - get_string('reportthisclick', 'hotpot', get_string('reportright', 'hotpot')),
344   - get_string('reportthisclick', 'hotpot', get_string('reportwrong', 'hotpot')),
345   - get_string('reportthisclick', 'hotpot', get_string('reportnottried', 'hotpot')),
346   - get_string('reportsofar', 'hotpot', get_string('reportright', 'hotpot')),
347   - get_string('reportsofar', 'hotpot', get_string('reportwrong', 'hotpot')),
348   - get_string('reportsofar', 'hotpot', get_string('reportnottried', 'hotpot')),
349   - get_string('reportthisclick', 'hotpot', get_string('reportanswers', 'hotpot')),
350   - get_string('reportthisclick', 'hotpot', get_string('reporthints', 'hotpot')),
351   - get_string('reportthisclick', 'hotpot', get_string($exercisetype=='JQuiz' ? 'reportshowanswer' : 'reportclues', 'hotpot')),
352   - get_string('reportthisclick', 'hotpot', get_string('reportevents', 'hotpot')),
353   - get_string('reportsofar', 'hotpot', get_string('reporthints', 'hotpot')),
354   - get_string('reportsofar', 'hotpot', get_string($exercisetype=='JQuiz' ? 'reportshowanswer' : 'reportclues', 'hotpot')),
355   - get_string('reportthisclick', 'hotpot', get_string('reportrawscore', 'hotpot')),
356   - get_string('reportthisclick', 'hotpot', get_string('reportmaxscore', 'hotpot')),
357   - get_string('reportthisclick', 'hotpot', $reportpercentscore),
358   - get_string('reportsofar', 'hotpot', get_string('reportrawscore', 'hotpot')),
359   - get_string('reportsofar', 'hotpot', get_string('reportmaxscore', 'hotpot')),
360   - get_string('reportsofar', 'hotpot', $reportpercentscore),
361   - get_string('reporthotpotscore', 'hotpot')
362   - );
363   - break;
364   - } // end switch
365   - }
366   - function set_align_and_wrap(&$table) {
367   - $count = count($table->head);
368   - for ($i=0; $i<$count; $i++) {
369   - if ($i==0 || $i==1 || $i==2 || $i==4 || $i==5 || $i>=7) {
370   - // numeric (and short text) columns
371   - $table->align[] = 'center';
372   - $table->wrap[] = '';
373   - } else {
374   - // text columns
375   - $table->align[] = 'left';
376   - $table->wrap[] = 'nowrap';
377   - }
378   - }
379   - }
380   - function set_data_exercise(&$cm, &$course, &$hotpot, &$questions, &$questionids, &$questioncount, &$blank) {
381   - // get exercise details (course name, section number, activity number, quiztype and question count)
382   - $record = get_record("course_sections", "id", $cm->section);
383   - $this->data['exercise'] = array(
384   - 'course' => $course->shortname,
385   - 'section' => empty($record) ? $blank : $record->section+1,
386   - 'number' => empty($record) ? $blank : array_search($cm->id, explode(',', $record->sequence))+1,
387   - 'name' => $hotpot->name,
388   - 'type' => $this->get_exercisetype($questions, $questionids, $blank),
389   - 'questioncount' => $questioncount
390   - );
391   - }
392   - function set_data_user(&$options, &$course, &$user) {
393   - global $CFG;
394   - // shortcut to first attempt record (which also hold user info)
395   - $attempt = &$user->attempts[0];
396   - $idnumber = $attempt->idnumber;
397   - if (empty($idnumber)) {
398   - $idnumber = fullname($attempt);
399   - }
400   - if ($options['reportformat']=='htm') {
401   - $idnumber = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$attempt->userid.'&course='.$course->id.'">'.$idnumber.'</a>';
402   - }
403   - $this->data['user'] = array(
404   - 'idnumber' => $idnumber,
405   - );
406   - }
407   - function set_data_attempt(&$attempt, &$strftimedate, &$strftimetime, &$blank) {
408   - global $CFG;
409   - $records = get_records_sql_menu("
410   - SELECT userid, MAX(time) AS logintime
411   - FROM {$CFG->prefix}log
412   - WHERE userid=$attempt->userid AND action='login' AND time<$attempt->timestart
413   - GROUP BY userid
414   - ");
415   - if (empty($records)) {
416   - $logindate = $blank;
417   - $logintime = $blank;
418   - } else {
419   - $logintime = $records[$attempt->userid];
420   - $logindate = trim(userdate($logintime, $strftimedate));
421   - $logintime = trim(userdate($logintime, $strftimetime));
422   - }
423   - $records = get_records_sql_menu("
424   - SELECT userid, MIN(time) AS logouttime
425   - FROM {$CFG->prefix}log
426   - WHERE userid=$attempt->userid AND action='logout' AND time>$attempt->cr_timefinish
427   - GROUP BY userid
428   - ");
429   - if (empty($records)) {
430   - $logouttime = $blank;
431   - } else {
432   - $logouttime = $records[$attempt->userid];
433   - $logouttime = trim(userdate($logouttime, $strftimetime));
434   - }
435   - $this->data['attempt'] = array(
436   - 'logindate' => $logindate,
437   - 'logintime' => $logintime,
438   - 'logouttime' => $logouttime,
439   - 'number' => $attempt->attempt,
440   - 'start' => trim(userdate($attempt->timestart, $strftimetime)),
441   - 'finish' => trim(userdate($attempt->cr_timefinish, $strftimetime)),
442   - );
443   - }
444   - function set_data_click($number, $time, $exercisetype, $click) {
445   - $types = array();
446   - foreach (array_keys($click['types']) as $type) {
447   - if ($exercisetype=='JQuiz' && $type=='clues') {
448   - $type = 'showanswer';
449   - } else {
450   - // remove final 's'
451   - $type = substr($type, 0, strlen($type)-1);
452   - }
453   - // $types[] = get_string($type, 'hotpot');
454   - $types[] = $type;
455   - }
456   - $this->data['click'] = array(
457   - 'number' => $number,
458   - 'time' => $time,
459   - 'type' => empty($types) ? '??' : implode(',', $types)
460   - );
461   - }
462   - function set_data_totals(&$click, &$clicks, &$questioncount, &$blank, &$attempt) {
463   - $count= array(
464   - 'click' => array(
465   - 'correct' => count($click['correct']),
466   - 'wrong' => count($click['wrong']),
467   - 'answers' => count($click['answers']),
468   - 'hints' => array_sum($click['hints']),
469   - 'clues' => array_sum($click['clues']),
470   - 'events' => array_sum($click['events']),
471   - 'score' => array_sum($click['score']),
472   - 'maxscore' => array_sum($click['weighting']),
473   - ),
474   - 'clicks' => array(
475   - 'correct' => count($clicks['correct']),
476   - 'wrong' => count($clicks['wrong']),
477   - 'answers' => count($clicks['answers']),
478   - 'hints' => array_sum($clicks['hints']),
479   - 'clues' => array_sum($clicks['clues']),
480   - 'score' => array_sum($clicks['score']),
481   - 'maxscore' => array_sum($clicks['weighting']),
482   - )
483   - );
484   - foreach ($count as $period=>$values) {
485   - $count[$period]['nottried'] = $questioncount - ($values['correct'] + $values['wrong']);
486   - $count[$period]['percent'] = empty($values['maxscore']) ? $blank : round(100 * $values['score'] / $values['maxscore'], 0);
487   - // blank out zero click values
488   - if ($period=='click') {
489   - foreach ($values as $detail=>$value) {
490   - if ($detail=='answers' || $detail=='hints' || $detail=='clues' || $detail=='events') {
491   - if (empty($value)) {
492   - $count[$period][$detail] = $blank;
493   - }
494   - }
495   - }
496   - }
497   - }
498   - $this->data['totals'] = array(
499   - $count['click']['answers'], // "q's tried"
500   - $count['clicks']['answers'], // "q's tried so far"
501   - $count['click']['correct'], // "right"
502   - $count['click']['wrong'], // "wrong"
503   - $count['click']['nottried'], // "not tried"
504   - $count['clicks']['correct'], // "right so far"
505   - $count['clicks']['wrong'], // "wrong so far"
506   - $count['clicks']['nottried'], // "not tried so far"
507   - $count['click']['answers'], // "answers",
508   - $count['click']['hints'], // "hints",
509   - $count['click']['clues'], // "clues",
510   - $count['click']['events'], // "answers",
511   - $count['clicks']['hints'], // "hints so far",
512   - $count['clicks']['clues'], // "clues so far",
513   - $count['click']['score'], // 'raw score',
514   - $count['click']['maxscore'], // 'max score',
515   - $count['click']['percent'], // '% score'
516   - $count['clicks']['score'], // 'raw score,
517   - $count['clicks']['maxscore'], // 'max score,
518   - $count['clicks']['percent'], // '% score
519   - $attempt->score // 'hotpot score'
520   - );
521   - }
522   - function update_event_count(&$click, $detail, $q) {
523   - if ($detail=='checks' || $detail=='hints' || $detail=='clues') {
524   - $click['types'][$detail] = true;
525   - }
526   - if ($detail=='answers' || $detail=='hints' || $detail=='clues') {
527   - $click['events'][$q] = isset($click['events'][$q]) ? $click['events'][$q]+1 : 1;
528   - }
529   - if ($detail=='answers') {
530   - $click['changes'][$q] = isset($click['changes'][$q]) ? $click['changes'][$q]+1 : 1;
531   - }
532   - }
533   - function set_data(&$cells, $zone) {
534   - foreach ($this->data[$zone] as $name=>$value) {
535   - $cells[] = $value;
536   - }
537   - }
538   -} // end class
539   -?>
  1 +<?php // $Id$
  2 +/// Overview report just displays a big table of all the attempts
  3 +class hotpot_report extends hotpot_default_report {
  4 + function display(&$hotpot, &$cm, &$course, &$users, &$attempts, &$questions, &$options) {
  5 + global $CFG;
  6 + // create the tables
  7 + $tables = array();
  8 + $this->create_clickreport_table($hotpot, $cm, $course, $users, $attempts, $questions, $options, $tables);
  9 + // print the tables
  10 + $this->print_report($course, $hotpot, $tables, $options);
  11 + return true;
  12 + }
  13 + function create_clickreport_table(&$hotpot, &$cm, &$course, &$users, &$attempts, &$questions, &$options, &$tables) {
  14 + global $CFG;
  15 + $is_html = ($options['reportformat']=='htm');
  16 + // time and date format strings // date format strings
  17 + $strftimetime = '%H:%M:%S';
  18 + $strftimedate = get_string('strftimedate');
  19 + // get the current time and max execution time
  20 + $start_report_time = microtime();
  21 + $max_execution_time = ini_get('max_execution_time');
  22 + $correct = get_string('reportcorrectsymbol', 'hotpot');
  23 + $wrong = get_string('reportwrongsymbol', 'hotpot');
  24 + $nottried = get_string('reportnottriedsymbol', 'hotpot');
  25 + // shortcuts for font tags
  26 + $blank = $is_html ? '&nbsp;' : "";
  27 + // store question count
  28 + $questioncount = count($questions);
  29 + // array to map columns onto question ids ($col => $id)
  30 + $questionids = array_keys($questions);
  31 + // store exercise type
  32 + $exercisetype = $this->get_exercisetype($questions, $questionids, $blank);
  33 + // initialize details ('events' must go last)
  34 + $details = array('checks', 'status', 'answers', 'changes', 'hints', 'clues', 'events');
  35 + // initialize $table
  36 + unset($table);
  37 + $table->border = 1;
  38 + $table->width = '100%';
  39 + // initialize legend, if necessary
  40 + if (!empty($options['reportshowlegend'])) {
  41 + $table->legend = array();
  42 + }
  43 + // start $table headings
  44 + $this->set_head($options, $table, 'exercise');
  45 + $this->set_head($options, $table, 'user');
  46 + $this->set_head($options, $table, 'attempt');
  47 + $this->set_head($options, $table, 'click');
  48 + // store clicktype column number
  49 + $clicktype_col = count($table->head)-1;
  50 + // finish $table headings
  51 + $this->set_head($options, $table, 'details', $exercisetype, $details, $questioncount);
  52 + $this->set_head($options, $table, 'totals', $exercisetype);
  53 + // set align and wrap
  54 + $this->set_align_and_wrap($table);
  55 + // is link to review allowed?
  56 + $allow_review = ($is_html && (isteacher($course->id) || $hotpot->review));
  57 + // initialize array of data values
  58 + $this->data = array();
  59 + // set exercise data values
  60 + $this->set_data_exercise($cm, $course, $hotpot, $questions, $questionids, $questioncount, $blank);
  61 + // add details of users' responses
  62 + foreach ($users as $user) {
  63 + $this->set_data_user($options, $course, $user);
  64 + unset($clickreportid);
  65 + foreach ($user->attempts as $attempt) {
  66 + // initialize totals for
  67 + $click = array(
  68 + 'qnumber' => array(),
  69 + 'correct' => array(),
  70 + 'wrong' => array(),
  71 + 'answers' => array(),
  72 + 'hints' => array(),
  73 + 'clues' => array(),
  74 + 'changes' => array(),
  75 + 'checks' => array(),
  76 + 'events' => array(),
  77 + 'score' => array(),
  78 + 'weighting' => array()
  79 + );
  80 + $clicktypes = array();
  81 + // is the start of a new attempt?
  82 + // (clicks in the same attempt have the same clickreportid)
  83 + if (!isset($clickreportid) || $clickreportid != $attempt->clickreportid) {
  84 + $clickcount = 1;
  85 + $clickreportid = $attempt->clickreportid;
  86 + // initialize totals for all clicks in this attempt
  87 + $clicks = $click; // $click has just been initialized
  88 + $this->set_data_attempt($attempt, $strftimedate, $strftimetime, $blank);
  89 + }
  90 + $cells = array();
  91 + $this->set_data($cells, 'exercise');
  92 + $this->set_data($cells, 'user');
  93 + $this->set_data($cells, 'attempt');
  94 + // get responses to questions in this attempt
  95 + foreach ($attempt->responses as $response) {
  96 + // set $q(uestion number)
  97 + $q = array_search($response->question, $questionids);
  98 + $click['qnumber'][$q] = true;
  99 + // was this question answered correctly?
  100 + if ($answer = hotpot_strings($response->correct)) {
  101 + // mark the question as correctly answered
  102 + if (empty($clicks['correct'][$q])) {
  103 + $click['correct'][$q] = true;
  104 + $clicks['correct'][$q] = true;
  105 + }
  106 + // unset 'wrong' flags, if necessary
  107 + if (isset($click['wrong'][$q])) {
  108 + unset($click['wrong'][$q]);
  109 + }
  110 + if (isset($clicks['wrong'][$q])) {
  111 + unset($clicks['wrong'][$q]);
  112 + }
  113 + // otherwise, was the question answered wrongly?
  114 + } else if ($answer = hotpot_strings($response->wrong)) {
  115 + // mark the question as wrongly answered
  116 + $click['wrong'][$q] = true;
  117 + $clicks['wrong'][$q] = true;
  118 + } else { // not correct or wrong (curious?!)
  119 + unset($answer);
  120 + }
  121 + if (!empty($click['correct'][$q]) || !empty($click['wrong'][$q])) {
  122 + $click['score'][$q] = $response->score;
  123 + $clicks['score'][$q] = $response->score;
  124 + $weighting = isset($response->weighting) ? $response->weighting : 100;
  125 + $click['weighting'][$q] = $weighting;
  126 + $clicks['weighting'][$q] =$weighting;
  127 + }
  128 + foreach($details as $detail) {
  129 + switch ($detail) {
  130 + case 'answers':
  131 + if (isset($answer) && is_string($answer) && !empty($answer)) {
  132 + $click[$detail][$q] = $answer;
  133 + }
  134 + break;
  135 + case 'hints':
  136 + case 'clues':
  137 + case 'checks':
  138 + if (isset($response->$detail) && is_numeric($response->$detail) && $response->$detail>0) {
  139 + if (!isset($click[$detail][$q]) || $click[$detail][$q] < $response->$detail) {
  140 + $click[$detail][$q] = $response->$detail;
  141 + }
  142 + }
  143 + break;
  144 + }
  145 + } // end foreach $detail
  146 + } // end foreach $response
  147 + $click['types'] = array();
  148 + $this->data['details'] = array();
  149 + foreach($details as $detail) {
  150 + for ($q=0; $q<$questioncount; $q++) {
  151 + switch ($detail) {
  152 + case 'status':
  153 + if (isset($clicks['correct'][$q])) {
  154 + $this->data['details'][] = $correct;
  155 + } else if (isset($clicks['wrong'][$q])) {
  156 + $this->data['details'][] = $wrong;
  157 + } else if (isset($click['qnumber'][$q])) {
  158 + $this->data['details'][] = $nottried;
  159 + } else { // this question did not appear in this attempt
  160 + $this->data['details'][] = $blank;
  161 + }
  162 + break;
  163 + case 'answers':
  164 + case 'hints':
  165 + case 'clues':
  166 + case 'checks':
  167 + if (!isset($clicks[$detail][$q])) {
  168 + if (!isset($click[$detail][$q])) {
  169 + $this->data['details'][] = $blank;
  170 + } else {
  171 + $clicks[$detail][$q] = $click[$detail][$q];
  172 + if ($detail=='answers') {
  173 + $this->set_legend($table, $q, $click[$detail][$q], $questions[$questionids[$q]]);
  174 + }
  175 + $this->data['details'][] = $click[$detail][$q];
  176 + $this->update_event_count($click, $detail, $q);
  177 + }
  178 + } else {
  179 + if (!isset($click[$detail][$q])) {
  180 + $this->data['details'][] = $blank;
  181 + } else {
  182 + $difference = '';
  183 + if ($detail=='answers') {
  184 + if ($click[$detail][$q] != $clicks[$detail][$q]) {
  185 + $pattern = '/^'.preg_quote($clicks[$detail][$q], '/').',/';
  186 + $difference = preg_replace($pattern, '', $click[$detail][$q], 1);
  187 + }
  188 + } else { // hints, clues, checks
  189 + if ($click[$detail][$q] > $clicks[$detail][$q]) {
  190 + $difference = $click[$detail][$q] - $clicks[$detail][$q];
  191 + }
  192 + }
  193 + if ($difference) {
  194 + $clicks[$detail][$q] = $click[$detail][$q];
  195 + $click[$detail][$q] = $difference;
  196 + if ($detail=='answers') {
  197 + $this->set_legend($table, $q, $difference, $questions[$questionids[$q]]);
  198 + }
  199 + $this->data['details'][] = $difference;
  200 + $this->update_event_count($click, $detail, $q);
  201 + } else {
  202 + unset($click[$detail][$q]);
  203 + $this->data['details'][] = $blank;
  204 + }
  205 + }
  206 + }
  207 + break;
  208 + case 'changes':
  209 + case 'events':
  210 + if (empty($click[$detail][$q])) {
  211 + $this->data['details'][] = $blank;
  212 + } else {
  213 + $this->data['details'][] = $click[$detail][$q];
  214 + }
  215 + break;
  216 + default:
  217 + // do nothing
  218 + break;
  219 + } // end switch
  220 + } // for $q
  221 + } // foreach $detail
  222 + // set data cell values for
  223 + $this->set_data_click(
  224 + $allow_review ? '<a href="review.php?hp='.$hotpot->id.'&attempt='.$attempt->id.'">'.$clickcount.'</a>' : $clickcount,
  225 + trim(userdate($attempt->timefinish, $strftimetime)),
  226 + $exercisetype,
  227 + $click
  228 + );
  229 + $this->set_data($cells, 'click');
  230 + $this->set_data($cells, 'details');
  231 + $this->set_data_totals($click, $clicks, $questioncount, $blank, $attempt);
  232 + $this->set_data($cells, 'totals');
  233 + $table->data[] = $cells;
  234 + $clickcount++;
  235 + } // end foreach $attempt
  236 + // insert 'tabledivider' between users
  237 + $table->data[] = 'hr';
  238 + } // end foreach $user
  239 + // remove final 'hr' from data rows
  240 + array_pop($table->data);
  241 + if ($is_html && $CFG->hotpot_showtimes) {
  242 + $count = count($users);
  243 + $duration = sprintf("%0.3f", microtime_diff($start_report_time, microtime()));
  244 + print "$count users processed in $duration seconds (".sprintf("%0.3f", $duration/$count).' secs/user)<hr size="1" noshade="noshade" />'."\n";
  245 + }
  246 + $tables[] = &$table;
  247 + $this->create_legend_table($tables, $table);
  248 + } // end function
  249 + function get_exercisetype(&$questions, &$questionids, &$blank) {
  250 + if (empty($questions)) {
  251 + $type = $blank;
  252 + } else {
  253 + switch ($questions[$questionids[0]]->type) {
  254 + case HOTPOT_JCB:
  255 + $type = "JCB";
  256 + break;
  257 + case HOTPOT_JCLOZE :
  258 + $type = "JCloze";
  259 + break;
  260 + case HOTPOT_JCROSS :
  261 + $type = "JCross";
  262 + break;
  263 + case HOTPOT_JMATCH :
  264 + $type = "JMatch";
  265 + break;
  266 + case HOTPOT_JMIX :
  267 + $type = "JMix";
  268 + break;
  269 + case HOTPOT_JQUIZ :
  270 + $type = "JQuiz";
  271 + break;
  272 + case HOTPOT_TEXTOYS_RHUBARB :
  273 + $type = "Rhubarb";
  274 + break;
  275 + case HOTPOT_TEXTOYS_SEQUITUR :
  276 + $type = "Sequitur";
  277 + break;
  278 + default:
  279 + $type = $blank;
  280 + }
  281 + }
  282 + return $type;
  283 + }
  284 + function set_head(&$options, &$table, $zone, $exercisetype='', $details=array(), $questioncount=0) {
  285 + if (empty($table->head)) {
  286 + $table->head = array();
  287 + }
  288 + switch ($zone) {
  289 + case 'exercise':
  290 + array_push($table->head,
  291 + get_string('reportcoursename', 'hotpot'),
  292 + get_string('reportsectionnumber', 'hotpot'),
  293 + get_string('reportexercisenumber', 'hotpot'),
  294 + get_string('reportexercisename', 'hotpot'),
  295 + get_string('reportexercisetype', 'hotpot'),
  296 + get_string('reportnumberofquestions', 'hotpot')
  297 + );
  298 + break;
  299 + case 'user':
  300 + array_push($table->head,
  301 + get_string('reportstudentid', 'hotpot'),
  302 + get_string('reportlogindate', 'hotpot'),
  303 + get_string('reportlogintime', 'hotpot'),
  304 + get_string('reportlogofftime', 'hotpot')
  305 + );
  306 + break;
  307 + case 'attempt':
  308 + array_push($table->head,
  309 + get_string('reportattemptnumber', 'hotpot'),
  310 + get_string('reportattemptstart', 'hotpot'),
  311 + get_string('reportattemptfinish', 'hotpot')
  312 + );
  313 + break;
  314 + case 'click':
  315 + array_push($table->head,
  316 + get_string('reportclicknumber', 'hotpot'),
  317 + get_string('reportclicktime', 'hotpot'),
  318 + get_string('reportclicktype', 'hotpot')
  319 + );
  320 + break;
  321 + case 'details':
  322 + foreach($details as $detail) {
  323 + if ($exercisetype=='JQuiz' && $detail=='clues') {
  324 + $detail = 'showanswer';
  325 + }
  326 + $detail = get_string("report$detail", 'hotpot');
  327 + for ($i=0; $i<$questioncount; $i++) {
  328 + $str = get_string('questionshort', 'hotpot', $i+1);
  329 + if ($i==0 || $options['reportformat']!='htm') {
  330 + $str = "$detail $str";
  331 + }
  332 + $table->head[] = $str;
  333 + }
  334 + }
  335 + break;
  336 + case 'totals':
  337 + $reportpercentscore =get_string('reportpercentscore', 'hotpot');
  338 + if (!function_exists('clean_getstring_data')) { // Moodle 1.4 (and less)
  339 + $reportpercentscore = str_replace('%', '%%', $reportpercentscore);
  340 + }
  341 + array_push($table->head,
  342 + get_string('reportthisclick', 'hotpot', get_string('reportquestionstried', 'hotpot')),
  343 + get_string('reportsofar', 'hotpot', get_string('reportquestionstried', 'hotpot')),
  344 + get_string('reportthisclick', 'hotpot', get_string('reportright', 'hotpot')),
  345 + get_string('reportthisclick', 'hotpot', get_string('reportwrong', 'hotpot')),
  346 + get_string('reportthisclick', 'hotpot', get_string('reportnottried', 'hotpot')),
  347 + get_string('reportsofar', 'hotpot', get_string('reportright', 'hotpot')),
  348 + get_string('reportsofar', 'hotpot', get_string('reportwrong', 'hotpot')),
  349 + get_string('reportsofar', 'hotpot', get_string('reportnottried', 'hotpot')),
  350 + get_string('reportthisclick', 'hotpot', get_string('reportanswers', 'hotpot')),
  351 + get_string('reportthisclick', 'hotpot', get_string('reporthints', 'hotpot')),
  352 + get_string('reportthisclick', 'hotpot', get_string($exercisetype=='JQuiz' ? 'reportshowanswer' : 'reportclues', 'hotpot')),
  353 + get_string('reportthisclick', 'hotpot', get_string('reportevents', 'hotpot')),
  354 + get_string('reportsofar', 'hotpot', get_string('reporthints', 'hotpot')),
  355 + get_string('reportsofar', 'hotpot', get_string($exercisetype=='JQuiz' ? 'reportshowanswer' : 'reportclues', 'hotpot')),
  356 + get_string('reportthisclick', 'hotpot', get_string('reportrawscore', 'hotpot')),
  357 + get_string('reportthisclick', 'hotpot', get_string('reportmaxscore', 'hotpot')),
  358 + get_string('reportthisclick', 'hotpot', $reportpercentscore),
  359 + get_string('reportsofar', 'hotpot', get_string('reportrawscore', 'hotpot')),
  360 + get_string('reportsofar', 'hotpot', get_string('reportmaxscore', 'hotpot')),
  361 + get_string('reportsofar', 'hotpot', $reportpercentscore),
  362 + get_string('reporthotpotscore', 'hotpot')
  363 + );
  364 + break;
  365 + } // end switch
  366 + }
  367 + function set_align_and_wrap(&$table) {
  368 + $count = count($table->head);
  369 + for ($i=0; $i<$count; $i++) {
  370 + if ($i==0 || $i==1 || $i==2 || $i==4 || $i==5 || $i>=7) {
  371 + // numeric (and short text) columns
  372 + $table->align[] = 'center';
  373 + $table->wrap[] = '';
  374 + } else {
  375 + // text columns
  376 + $table->align[] = 'left';
  377 + $table->wrap[] = 'nowrap';
  378 + }
  379 + }
  380 + }
  381 + function set_data_exercise(&$cm, &$course, &$hotpot, &$questions, &$questionids, &$questioncount, &$blank) {
  382 + // get exercise details (course name, section number, activity number, quiztype and question count)
  383 + $record = get_record("course_sections", "id", $cm->section);
  384 + $this->data['exercise'] = array(
  385 + 'course' => $course->shortname,
  386 + 'section' => empty($record) ? $blank : $record->section+1,
  387 + 'number' => empty($record) ? $blank : array_search($cm->id, explode(',', $record->sequence))+1,
  388 + 'name' => $hotpot->name,
  389 + 'type' => $this->get_exercisetype($questions, $questionids, $blank),
  390 + 'questioncount' => $questioncount
  391 + );
  392 + }
  393 + function set_data_user(&$options, &$course, &$user) {
  394 + global $CFG;
  395 + // shortcut to first attempt record (which also hold user info)
  396 + $attempt = &$user->attempts[0];
  397 + $idnumber = $attempt->idnumber;
  398 + if (empty($idnumber)) {
  399 + $idnumber = fullname($attempt);
  400 + }
  401 + if ($options['reportformat']=='htm') {
  402 + $idnumber = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$attempt->userid.'&course='.$course->id.'">'.$idnumber.'</a>';
  403 + }
  404 + $this->data['user'] = array(
  405 + 'idnumber' => $idnumber,
  406 + );
  407 + }
  408 + function set_data_attempt(&$attempt, &$strftimedate, &$strftimetime, &$blank) {
  409 + global $CFG;
  410 + $records = get_records_sql_menu("
  411 + SELECT userid, MAX(time) AS logintime
  412 + FROM {$CFG->prefix}log
  413 + WHERE userid=$attempt->userid AND action='login' AND time<$attempt->timestart
  414 + GROUP BY userid
  415 + ");
  416 + if (empty($records)) {
  417 + $logindate = $blank;
  418 + $logintime = $blank;
  419 + } else {
  420 + $logintime = $records[$attempt->userid];
  421 + $logindate = trim(userdate($logintime, $strftimedate));
  422 + $logintime = trim(userdate($logintime, $strftimetime));
  423 + }
  424 + $records = get_records_sql_menu("
  425 + SELECT userid, MIN(time) AS logouttime
  426 + FROM {$CFG->prefix}log
  427 + WHERE userid=$attempt->userid AND action='logout' AND time>$attempt->cr_timefinish
  428 + GROUP BY userid
  429 + ");
  430 + if (empty($records)) {
  431 + $logouttime = $blank;
  432 + } else {
  433 + $logouttime = $records[$attempt->userid];
  434 + $logouttime = trim(userdate($logouttime, $strftimetime));
  435 + }
  436 + $this->data['attempt'] = array(
  437 + 'logindate' => $logindate,
  438 + 'logintime' => $logintime,
  439 + 'logouttime' => $logouttime,
  440 + 'number' => $attempt->attempt,
  441 + 'start' => trim(userdate($attempt->timestart, $strftimetime)),
  442 + 'finish' => trim(userdate($attempt->cr_timefinish, $strftimetime)),
  443 + );
  444 + }
  445 + function set_data_click($number, $time, $exercisetype, $click) {
  446 + $types = array();
  447 + foreach (array_keys($click['types']) as $type) {
  448 + if ($exercisetype=='JQuiz' && $type=='clues') {
  449 + $type = 'showanswer';
  450 + } else {
  451 + // remove final 's'
  452 + $type = substr($type, 0, strlen($type)-1);
  453 + }
  454 + // $types[] = get_string($type, 'hotpot');
  455 + $types[] = $type;
  456 + }
  457 + $this->data['click'] = array(
  458 + 'number' => $number,
  459 + 'time' => $time,
  460 + 'type' => empty($types) ? '??' : implode(',', $types)
  461 + );
  462 + }
  463 + function set_data_totals(&$click, &$clicks, &$questioncount, &$blank, &$attempt) {
  464 + $count= array(
  465 + 'click' => array(
  466 + 'correct' => count($click['correct']),
  467 + 'wrong' => count($click['wrong']),
  468 + 'answers' => count($click['answers']),
  469 + 'hints' => array_sum($click['hints']),
  470 + 'clues' => array_sum($click['clues']),
  471 + 'events' => array_sum($click['events']),
  472 + 'score' => array_sum($click['score']),
  473 + 'maxscore' => array_sum($click['weighting']),
  474 + ),