-<?php // $Id$
-/// Overview report just displays a big table of all the attempts
-class hotpot_report extends hotpot_default_report {
- function display(&$hotpot, &$cm, &$course, &$users, &$attempts, &$questions, &$options) {
- global $CFG;
- // create the table
- $this->create_clickreport_table($hotpot, $cm, $course, $users, $attempts, $questions, $options, $tables=array());
- // print the table
- $this->print_report($course, $hotpot, $tables, $options);
- return true;
- }
- function create_clickreport_table(&$hotpot, &$cm, &$course, &$users, &$attempts, &$questions, &$options, &$tables) {
- global $CFG;
- $is_html = ($options['reportformat']=='htm');
- // time and date format strings // date format strings
- $strftimetime = '%H:%M:%S';
- $strftimedate = get_string('strftimedate');
- // get the current time and max execution time
- $start_report_time = microtime();
- $max_execution_time = ini_get('max_execution_time');
- $correct = get_string('reportcorrectsymbol', 'hotpot');
- $wrong = get_string('reportwrongsymbol', 'hotpot');
- $nottried = get_string('reportnottriedsymbol', 'hotpot');
- // shortcuts for font tags
- $blank = $is_html ? ' ' : "";
- // store question count
- $questioncount = count($questions);
- // array to map columns onto question ids ($col => $id)
- $questionids = array_keys($questions);
- // store exercise type
- $exercisetype = $this->get_exercisetype($questions, $questionids, $blank);
- // initialize details ('events' must go last)
- $details = array('checks', 'status', 'answers', 'changes', 'hints', 'clues', 'events');
- // initialize $table
- unset($table);
- $table->border = 1;
- $table->width = '100%';
- // initialize legend, if necessary
- if (!empty($options['reportshowlegend'])) {
- $table->legend = array();
- }
- // start $table headings
- $this->set_head($options, $table, 'exercise');
- $this->set_head($options, $table, 'user');
- $this->set_head($options, $table, 'attempt');
- $this->set_head($options, $table, 'click');
- // store clicktype column number
- $clicktype_col = count($table->head)-1;
- // finish $table headings
- $this->set_head($options, $table, 'details', $exercisetype, $details, $questioncount);
- $this->set_head($options, $table, 'totals', $exercisetype);
- // set align and wrap
- $this->set_align_and_wrap($table);
- // is link to review allowed?
- $allow_review = ($is_html && (isteacher($course->id) || $hotpot->review));
- // initialize array of data values
- $this->data = array();
- // set exercise data values
- $this->set_data_exercise($cm, $course, $hotpot, $questions, $questionids, $questioncount, $blank);
- // add details of users' responses
- foreach ($users as $user) {
- $this->set_data_user($options, $course, $user);
- unset($clickreportid);
- foreach ($user->attempts as $attempt) {
- // initialize totals for
- $click = array(
- 'qnumber' => array(),
- 'correct' => array(),
- 'wrong' => array(),
- 'answers' => array(),
- 'hints' => array(),
- 'clues' => array(),
- 'changes' => array(),
- 'checks' => array(),
- 'events' => array(),
- 'score' => array(),
- 'weighting' => array()
- );
- $clicktypes = array();
- // is the start of a new attempt?
- // (clicks in the same attempt have the same clickreportid)
- if (!isset($clickreportid) || $clickreportid != $attempt->clickreportid) {
- $clickcount = 1;
- $clickreportid = $attempt->clickreportid;
- // initialize totals for all clicks in this attempt
- $clicks = $click; // $click has just been initialized
- $this->set_data_attempt($attempt, $strftimedate, $strftimetime, $blank);
- }
- $cells = array();
- $this->set_data($cells, 'exercise');
- $this->set_data($cells, 'user');
- $this->set_data($cells, 'attempt');
- // get responses to questions in this attempt
- foreach ($attempt->responses as $response) {
- // set $q(uestion number)
- $q = array_search($response->question, $questionids);
- $click['qnumber'][$q] = true;
- // was this question answered correctly?
- if ($answer = hotpot_strings($response->correct)) {
- // mark the question as correctly answered
- if (empty($clicks['correct'][$q])) {
- $click['correct'][$q] = true;
- $clicks['correct'][$q] = true;
- }
- // unset 'wrong' flags, if necessary
- if (isset($click['wrong'][$q])) {
- unset($click['wrong'][$q]);
- }
- if (isset($clicks['wrong'][$q])) {
- unset($clicks['wrong'][$q]);
- }
- // otherwise, was the question answered wrongly?
- } else if ($answer = hotpot_strings($response->wrong)) {
- // mark the question as wrongly answered
- $click['wrong'][$q] = true;
- $clicks['wrong'][$q] = true;
- } else { // not correct or wrong (curious?!)
- unset($answer);
- }
- if (!empty($click['correct'][$q]) || !empty($click['wrong'][$q])) {
- $click['score'][$q] = $response->score;
- $clicks['score'][$q] = $response->score;
- $weighting = isset($response->weighting) ? $response->weighting : 100;
- $click['weighting'][$q] = $weighting;
- $clicks['weighting'][$q] =$weighting;
- }
- foreach($details as $detail) {
- switch ($detail) {
- case 'answers':
- if (isset($answer) && is_string($answer) && !empty($answer)) {
- $click[$detail][$q] = $answer;
- }
- break;
- case 'hints':
- case 'clues':
- case 'checks':
- if (isset($response->$detail) && is_numeric($response->$detail) && $response->$detail>0) {
- if (!isset($click[$detail][$q]) || $click[$detail][$q] < $response->$detail) {
- $click[$detail][$q] = $response->$detail;
- }
- }
- break;
- }
- } // end foreach $detail
- } // end foreach $response
- $click['types'] = array();
- $this->data['details'] = array();
- foreach($details as $detail) {
- for ($q=0; $q<$questioncount; $q++) {
- switch ($detail) {
- case 'status':
- if (isset($clicks['correct'][$q])) {
- $this->data['details'][] = $correct;
- } else if (isset($clicks['wrong'][$q])) {
- $this->data['details'][] = $wrong;
- } else if (isset($click['qnumber'][$q])) {
- $this->data['details'][] = $nottried;
- } else { // this question did not appear in this attempt
- $this->data['details'][] = $blank;
- }
- break;
- case 'answers':
- case 'hints':
- case 'clues':
- case 'checks':
- if (!isset($clicks[$detail][$q])) {
- if (!isset($click[$detail][$q])) {
- $this->data['details'][] = $blank;
- } else {
- $clicks[$detail][$q] = $click[$detail][$q];
- if ($detail=='answers') {
- $this->set_legend($table, $q, $click[$detail][$q], $questions[$questionids[$q]]);
- }
- $this->data['details'][] = $click[$detail][$q];
- $this->update_event_count($click, $detail, $q);
- }
- } else {
- if (!isset($click[$detail][$q])) {
- $this->data['details'][] = $blank;
- } else {
- $difference = '';
- if ($detail=='answers') {
- if ($click[$detail][$q] != $clicks[$detail][$q]) {
- $pattern = '/^'.preg_quote($clicks[$detail][$q], '/').',/';
- $difference = preg_replace($pattern, '', $click[$detail][$q], 1);
- }
- } else { // hints, clues, checks
- if ($click[$detail][$q] > $clicks[$detail][$q]) {
- $difference = $click[$detail][$q] - $clicks[$detail][$q];
- }
- }
- if ($difference) {
- $clicks[$detail][$q] = $click[$detail][$q];
- $click[$detail][$q] = $difference;
- if ($detail=='answers') {
- $this->set_legend($table, $q, $difference, $questions[$questionids[$q]]);
- }
- $this->data['details'][] = $difference;
- $this->update_event_count($click, $detail, $q);
- } else {
- unset($click[$detail][$q]);
- $this->data['details'][] = $blank;
- }
- }
- }
- break;
- case 'changes':
- case 'events':
- if (empty($click[$detail][$q])) {
- $this->data['details'][] = $blank;
- } else {
- $this->data['details'][] = $click[$detail][$q];
- }
- break;
- default:
- // do nothing
- break;
- } // end switch
- } // for $q
- } // foreach $detail
- // set data cell values for
- $this->set_data_click(
- $allow_review ? '<a href="review.php?hp='.$hotpot->id.'&attempt='.$attempt->id.'">'.$clickcount.'</a>' : $clickcount,
- trim(userdate($attempt->timefinish, $strftimetime)),
- $exercisetype,
- $click
- );
- $this->set_data($cells, 'click');
- $this->set_data($cells, 'details');
- $this->set_data_totals($click, $clicks, $questioncount, $blank, $attempt);
- $this->set_data($cells, 'totals');
- $table->data[] = $cells;
- $clickcount++;
- } // end foreach $attempt
- // insert 'tabledivider' between users
- $table->data[] = 'hr';
- } // end foreach $user
- // remove final 'hr' from data rows
- array_pop($table->data);
- if ($is_html && $CFG->hotpot_showtimes) {
- $count = count($users);
- $duration = sprintf("%0.3f", microtime_diff($start_report_time, microtime()));
- print "$count users processed in $duration seconds (".sprintf("%0.3f", $duration/$count).' secs/user)<hr size="1" noshade="noshade" />'."\n";
- }
- $tables[] = &$table;
- $this->create_legend_table($tables, $table);
- } // end function
- function get_exercisetype(&$questions, &$questionids, &$blank) {
- if (empty($questions)) {
- $type = $blank;
- } else {
- switch ($questions[$questionids[0]]->type) {
- case HOTPOT_JCB:
- $type = "JCB";
- break;
- case HOTPOT_JCLOZE :
- $type = "JCloze";
- break;
- case HOTPOT_JCROSS :
- $type = "JCross";
- break;
- case HOTPOT_JMATCH :
- $type = "JMatch";
- break;
- case HOTPOT_JMIX :
- $type = "JMix";
- break;
- case HOTPOT_JQUIZ :
- $type = "JQuiz";
- break;
- case HOTPOT_TEXTOYS_RHUBARB :
- $type = "Rhubarb";
- break;
- case HOTPOT_TEXTOYS_SEQUITUR :
- $type = "Sequitur";
- break;
- default:
- $type = $blank;
- }
- }
- return $type;
- }
- function set_head(&$options, &$table, $zone, $exercisetype='', $details=array(), $questioncount=0) {
- if (empty($table->head)) {
- $table->head = array();
- }
- switch ($zone) {
- case 'exercise':
- array_push($table->head,
- get_string('reportcoursename', 'hotpot'),
- get_string('reportsectionnumber', 'hotpot'),
- get_string('reportexercisenumber', 'hotpot'),
- get_string('reportexercisename', 'hotpot'),
- get_string('reportexercisetype', 'hotpot'),
- get_string('reportnumberofquestions', 'hotpot')
- );
- break;
- case 'user':
- array_push($table->head,
- get_string('reportstudentid', 'hotpot'),
- get_string('reportlogindate', 'hotpot'),
- get_string('reportlogintime', 'hotpot'),
- get_string('reportlogofftime', 'hotpot')
- );
- break;
- case 'attempt':
- array_push($table->head,
- get_string('reportattemptnumber', 'hotpot'),
- get_string('reportattemptstart', 'hotpot'),
- get_string('reportattemptfinish', 'hotpot')
- );
- break;
- case 'click':
- array_push($table->head,
- get_string('reportclicknumber', 'hotpot'),
- get_string('reportclicktime', 'hotpot'),
- get_string('reportclicktype', 'hotpot')
- );
- break;
- case 'details':
- foreach($details as $detail) {
- if ($exercisetype=='JQuiz' && $detail=='clues') {
- $detail = 'showanswer';
- }
- $detail = get_string("report$detail", 'hotpot');
- for ($i=0; $i<$questioncount; $i++) {
- $str = get_string('questionshort', 'hotpot', $i+1);
- if ($i==0 || $options['reportformat']!='htm') {
- $str = "$detail $str";
- }
- $table->head[] = $str;
- }
- }
- break;
- case 'totals':
- $reportpercentscore =get_string('reportpercentscore', 'hotpot');
- if (!function_exists('clean_getstring_data')) { // Moodle 1.4 (and less)
- $reportpercentscore = str_replace('%', '%%', $reportpercentscore);
- }
- array_push($table->head,
- get_string('reportthisclick', 'hotpot', get_string('reportquestionstried', 'hotpot')),
- get_string('reportsofar', 'hotpot', get_string('reportquestionstried', 'hotpot')),
- get_string('reportthisclick', 'hotpot', get_string('reportright', 'hotpot')),
- get_string('reportthisclick', 'hotpot', get_string('reportwrong', 'hotpot')),
- get_string('reportthisclick', 'hotpot', get_string('reportnottried', 'hotpot')),
- get_string('reportsofar', 'hotpot', get_string('reportright', 'hotpot')),
- get_string('reportsofar', 'hotpot', get_string('reportwrong', 'hotpot')),
- get_string('reportsofar', 'hotpot', get_string('reportnottried', 'hotpot')),
- get_string('reportthisclick', 'hotpot', get_string('reportanswers', 'hotpot')),
- get_string('reportthisclick', 'hotpot', get_string('reporthints', 'hotpot')),
- get_string('reportthisclick', 'hotpot', get_string($exercisetype=='JQuiz' ? 'reportshowanswer' : 'reportclues', 'hotpot')),
- get_string('reportthisclick', 'hotpot', get_string('reportevents', 'hotpot')),
- get_string('reportsofar', 'hotpot', get_string('reporthints', 'hotpot')),
- get_string('reportsofar', 'hotpot', get_string($exercisetype=='JQuiz' ? 'reportshowanswer' : 'reportclues', 'hotpot')),
- get_string('reportthisclick', 'hotpot', get_string('reportrawscore', 'hotpot')),
- get_string('reportthisclick', 'hotpot', get_string('reportmaxscore', 'hotpot')),
- get_string('reportthisclick', 'hotpot', $reportpercentscore),
- get_string('reportsofar', 'hotpot', get_string('reportrawscore', 'hotpot')),
- get_string('reportsofar', 'hotpot', get_string('reportmaxscore', 'hotpot')),
- get_string('reportsofar', 'hotpot', $reportpercentscore),
- get_string('reporthotpotscore', 'hotpot')
- );
- break;
- } // end switch
- }
- function set_align_and_wrap(&$table) {
- $count = count($table->head);
- for ($i=0; $i<$count; $i++) {
- if ($i==0 || $i==1 || $i==2 || $i==4 || $i==5 || $i>=7) {
- // numeric (and short text) columns
- $table->align[] = 'center';
- $table->wrap[] = '';
- } else {
- // text columns
- $table->align[] = 'left';
- $table->wrap[] = 'nowrap';
- }
- }
- }
- function set_data_exercise(&$cm, &$course, &$hotpot, &$questions, &$questionids, &$questioncount, &$blank) {
- // get exercise details (course name, section number, activity number, quiztype and question count)
- $record = get_record("course_sections", "id", $cm->section);
- $this->data['exercise'] = array(
- 'course' => $course->shortname,
- 'section' => empty($record) ? $blank : $record->section+1,
- 'number' => empty($record) ? $blank : array_search($cm->id, explode(',', $record->sequence))+1,
- 'name' => $hotpot->name,
- 'type' => $this->get_exercisetype($questions, $questionids, $blank),
- 'questioncount' => $questioncount
- );
- }
- function set_data_user(&$options, &$course, &$user) {
- global $CFG;
- // shortcut to first attempt record (which also hold user info)
- $attempt = &$user->attempts[0];
- $idnumber = $attempt->idnumber;
- if (empty($idnumber)) {
- $idnumber = fullname($attempt);
- }
- if ($options['reportformat']=='htm') {
- $idnumber = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$attempt->userid.'&course='.$course->id.'">'.$idnumber.'</a>';
- }
- $this->data['user'] = array(
- 'idnumber' => $idnumber,
- );
- }
- function set_data_attempt(&$attempt, &$strftimedate, &$strftimetime, &$blank) {
- global $CFG;
- $records = get_records_sql_menu("
- SELECT userid, MAX(time) AS logintime
- FROM {$CFG->prefix}log
- WHERE userid=$attempt->userid AND action='login' AND time<$attempt->timestart
- GROUP BY userid
- ");
- if (empty($records)) {
- $logindate = $blank;
- $logintime = $blank;
- } else {
- $logintime = $records[$attempt->userid];
- $logindate = trim(userdate($logintime, $strftimedate));
- $logintime = trim(userdate($logintime, $strftimetime));
- }
- $records = get_records_sql_menu("
- SELECT userid, MIN(time) AS logouttime
- FROM {$CFG->prefix}log
- WHERE userid=$attempt->userid AND action='logout' AND time>$attempt->cr_timefinish
- GROUP BY userid
- ");
- if (empty($records)) {
- $logouttime = $blank;
- } else {
- $logouttime = $records[$attempt->userid];
- $logouttime = trim(userdate($logouttime, $strftimetime));
- }
- $this->data['attempt'] = array(
- 'logindate' => $logindate,
- 'logintime' => $logintime,
- 'logouttime' => $logouttime,
- 'number' => $attempt->attempt,
- 'start' => trim(userdate($attempt->timestart, $strftimetime)),
- 'finish' => trim(userdate($attempt->cr_timefinish, $strftimetime)),
- );
- }
- function set_data_click($number, $time, $exercisetype, $click) {
- $types = array();
- foreach (array_keys($click['types']) as $type) {
- if ($exercisetype=='JQuiz' && $type=='clues') {
- $type = 'showanswer';
- } else {
- // remove final 's'
- $type = substr($type, 0, strlen($type)-1);
- }
- // $types[] = get_string($type, 'hotpot');
- $types[] = $type;
- }
- $this->data['click'] = array(
- 'number' => $number,
- 'time' => $time,
- 'type' => empty($types) ? '??' : implode(',', $types)
- );
- }
- function set_data_totals(&$click, &$clicks, &$questioncount, &$blank, &$attempt) {
- $count= array(
- 'click' => array(
- 'correct' => count($click['correct']),
- 'wrong' => count($click['wrong']),
- 'answers' => count($click['answers']),
- 'hints' => array_sum($click['hints']),
- 'clues' => array_sum($click['clues']),
- 'events' => array_sum($click['events']),
- 'score' => array_sum($click['score']),
- 'maxscore' => array_sum($click['weighting']),
- ),
- 'clicks' => array(
- 'correct' => count($clicks['correct']),
- 'wrong' => count($clicks['wrong']),
- 'answers' => count($clicks['answers']),
- 'hints' => array_sum($clicks['hints']),
- 'clues' => array_sum($clicks['clues']),
- 'score' => array_sum($clicks['score']),
- 'maxscore' => array_sum($clicks['weighting']),
- )
- );
- foreach ($count as $period=>$values) {
- $count[$period]['nottried'] = $questioncount - ($values['correct'] + $values['wrong']);
- $count[$period]['percent'] = empty($values['maxscore']) ? $blank : round(100 * $values['score'] / $values['maxscore'], 0);
- // blank out zero click values
- if ($period=='click') {
- foreach ($values as $detail=>$value) {
- if ($detail=='answers' || $detail=='hints' || $detail=='clues' || $detail=='events') {
- if (empty($value)) {
- $count[$period][$detail] = $blank;
- }
- }
- }
- }
- }
- $this->data['totals'] = array(
- $count['click']['answers'], // "q's tried"
- $count['clicks']['answers'], // "q's tried so far"
- $count['click']['correct'], // "right"
- $count['click']['wrong'], // "wrong"
- $count['click']['nottried'], // "not tried"
- $count['clicks']['correct'], // "right so far"
- $count['clicks']['wrong'], // "wrong so far"
- $count['clicks']['nottried'], // "not tried so far"
- $count['click']['answers'], // "answers",
- $count['click']['hints'], // "hints",
- $count['click']['clues'], // "clues",
- $count['click']['events'], // "answers",
- $count['clicks']['hints'], // "hints so far",
- $count['clicks']['clues'], // "clues so far",
- $count['click']['score'], // 'raw score',
- $count['click']['maxscore'], // 'max score',
- $count['click']['percent'], // '% score'
- $count['clicks']['score'], // 'raw score,
- $count['clicks']['maxscore'], // 'max score,
- $count['clicks']['percent'], // '% score
- $attempt->score // 'hotpot score'
- );
- }
- function update_event_count(&$click, $detail, $q) {
- if ($detail=='checks' || $detail=='hints' || $detail=='clues') {
- $click['types'][$detail] = true;
- }
- if ($detail=='answers' || $detail=='hints' || $detail=='clues') {
- $click['events'][$q] = isset($click['events'][$q]) ? $click['events'][$q]+1 : 1;
- }
- if ($detail=='answers') {
- $click['changes'][$q] = isset($click['changes'][$q]) ? $click['changes'][$q]+1 : 1;
- }
- }
- function set_data(&$cells, $zone) {
- foreach ($this->data[$zone] as $name=>$value) {
- $cells[] = $value;
- }
- }
-} // end class
-?>
+<?php // $Id$\r
+/// Overview report just displays a big table of all the attempts\r
+class hotpot_report extends hotpot_default_report {\r
+ function display(&$hotpot, &$cm, &$course, &$users, &$attempts, &$questions, &$options) {\r
+ global $CFG;\r
+ // create the tables\r
+ $tables = array();\r
+ $this->create_clickreport_table($hotpot, $cm, $course, $users, $attempts, $questions, $options, $tables);\r
+ // print the tables\r
+ $this->print_report($course, $hotpot, $tables, $options);\r
+ return true;\r
+ }\r
+ function create_clickreport_table(&$hotpot, &$cm, &$course, &$users, &$attempts, &$questions, &$options, &$tables) {\r
+ global $CFG;\r
+ $is_html = ($options['reportformat']=='htm');\r
+ // time and date format strings // date format strings\r
+ $strftimetime = '%H:%M:%S';\r
+ $strftimedate = get_string('strftimedate');\r
+ // get the current time and max execution time\r
+ $start_report_time = microtime();\r
+ $max_execution_time = ini_get('max_execution_time');\r
+ $correct = get_string('reportcorrectsymbol', 'hotpot');\r
+ $wrong = get_string('reportwrongsymbol', 'hotpot');\r
+ $nottried = get_string('reportnottriedsymbol', 'hotpot');\r
+ // shortcuts for font tags\r
+ $blank = $is_html ? ' ' : "";\r
+ // store question count\r
+ $questioncount = count($questions);\r
+ // array to map columns onto question ids ($col => $id)\r
+ $questionids = array_keys($questions);\r
+ // store exercise type\r
+ $exercisetype = $this->get_exercisetype($questions, $questionids, $blank);\r
+ // initialize details ('events' must go last)\r
+ $details = array('checks', 'status', 'answers', 'changes', 'hints', 'clues', 'events');\r
+ // initialize $table\r
+ unset($table);\r
+ $table->border = 1;\r
+ $table->width = '100%';\r
+ // initialize legend, if necessary\r
+ if (!empty($options['reportshowlegend'])) {\r
+ $table->legend = array();\r
+ }\r
+ // start $table headings\r
+ $this->set_head($options, $table, 'exercise');\r
+ $this->set_head($options, $table, 'user');\r
+ $this->set_head($options, $table, 'attempt');\r
+ $this->set_head($options, $table, 'click');\r
+ // store clicktype column number\r
+ $clicktype_col = count($table->head)-1;\r
+ // finish $table headings\r
+ $this->set_head($options, $table, 'details', $exercisetype, $details, $questioncount);\r
+ $this->set_head($options, $table, 'totals', $exercisetype);\r
+ // set align and wrap\r
+ $this->set_align_and_wrap($table);\r
+ // is link to review allowed?\r
+ $allow_review = ($is_html && (isteacher($course->id) || $hotpot->review));\r
+ // initialize array of data values\r
+ $this->data = array();\r
+ // set exercise data values\r
+ $this->set_data_exercise($cm, $course, $hotpot, $questions, $questionids, $questioncount, $blank);\r
+ // add details of users' responses\r
+ foreach ($users as $user) {\r
+ $this->set_data_user($options, $course, $user);\r
+ unset($clickreportid);\r
+ foreach ($user->attempts as $attempt) {\r
+ // initialize totals for\r
+ $click = array(\r
+ 'qnumber' => array(),\r
+ 'correct' => array(),\r
+ 'wrong' => array(),\r
+ 'answers' => array(),\r
+ 'hints' => array(),\r
+ 'clues' => array(),\r
+ 'changes' => array(),\r
+ 'checks' => array(),\r
+ 'events' => array(),\r
+ 'score' => array(),\r
+ 'weighting' => array()\r
+ );\r
+ $clicktypes = array();\r
+ // is the start of a new attempt?\r
+ // (clicks in the same attempt have the same clickreportid)\r
+ if (!isset($clickreportid) || $clickreportid != $attempt->clickreportid) {\r
+ $clickcount = 1;\r
+ $clickreportid = $attempt->clickreportid;\r
+ // initialize totals for all clicks in this attempt\r
+ $clicks = $click; // $click has just been initialized\r
+ $this->set_data_attempt($attempt, $strftimedate, $strftimetime, $blank);\r
+ }\r
+ $cells = array();\r
+ $this->set_data($cells, 'exercise');\r
+ $this->set_data($cells, 'user');\r
+ $this->set_data($cells, 'attempt');\r
+ // get responses to questions in this attempt\r
+ foreach ($attempt->responses as $response) {\r
+ // set $q(uestion number)\r
+ $q = array_search($response->question, $questionids);\r
+ $click['qnumber'][$q] = true;\r
+ // was this question answered correctly?\r
+ if ($answer = hotpot_strings($response->correct)) {\r
+ // mark the question as correctly answered\r
+ if (empty($clicks['correct'][$q])) {\r
+ $click['correct'][$q] = true;\r
+ $clicks['correct'][$q] = true;\r
+ }\r
+ // unset 'wrong' flags, if necessary\r
+ if (isset($click['wrong'][$q])) {\r
+ unset($click['wrong'][$q]);\r
+ }\r
+ if (isset($clicks['wrong'][$q])) {\r
+ unset($clicks['wrong'][$q]);\r
+ }\r
+ // otherwise, was the question answered wrongly?\r
+ } else if ($answer = hotpot_strings($response->wrong)) {\r
+ // mark the question as wrongly answered\r
+ $click['wrong'][$q] = true;\r
+ $clicks['wrong'][$q] = true;\r
+ } else { // not correct or wrong (curious?!)\r
+ unset($answer);\r
+ }\r
+ if (!empty($click['correct'][$q]) || !empty($click['wrong'][$q])) {\r
+ $click['score'][$q] = $response->score;\r
+ $clicks['score'][$q] = $response->score;\r
+ $weighting = isset($response->weighting) ? $response->weighting : 100;\r
+ $click['weighting'][$q] = $weighting;\r
+ $clicks['weighting'][$q] =$weighting;\r
+ }\r
+ foreach($details as $detail) {\r
+ switch ($detail) {\r
+ case 'answers':\r
+ if (isset($answer) && is_string($answer) && !empty($answer)) {\r
+ $click[$detail][$q] = $answer;\r
+ }\r
+ break;\r
+ case 'hints':\r
+ case 'clues':\r
+ case 'checks':\r
+ if (isset($response->$detail) && is_numeric($response->$detail) && $response->$detail>0) {\r
+ if (!isset($click[$detail][$q]) || $click[$detail][$q] < $response->$detail) {\r
+ $click[$detail][$q] = $response->$detail;\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ } // end foreach $detail\r
+ } // end foreach $response\r
+ $click['types'] = array();\r
+ $this->data['details'] = array();\r
+ foreach($details as $detail) {\r
+ for ($q=0; $q<$questioncount; $q++) {\r
+ switch ($detail) {\r
+ case 'status':\r
+ if (isset($clicks['correct'][$q])) {\r
+ $this->data['details'][] = $correct;\r
+ } else if (isset($clicks['wrong'][$q])) {\r
+ $this->data['details'][] = $wrong;\r
+ } else if (isset($click['qnumber'][$q])) {\r
+ $this->data['details'][] = $nottried;\r
+ } else { // this question did not appear in this attempt\r
+ $this->data['details'][] = $blank;\r
+ }\r
+ break;\r
+ case 'answers':\r
+ case 'hints':\r
+ case 'clues':\r
+ case 'checks':\r
+ if (!isset($clicks[$detail][$q])) {\r
+ if (!isset($click[$detail][$q])) {\r
+ $this->data['details'][] = $blank;\r
+ } else {\r
+ $clicks[$detail][$q] = $click[$detail][$q];\r
+ if ($detail=='answers') {\r
+ $this->set_legend($table, $q, $click[$detail][$q], $questions[$questionids[$q]]);\r
+ }\r
+ $this->data['details'][] = $click[$detail][$q];\r
+ $this->update_event_count($click, $detail, $q);\r
+ }\r
+ } else {\r
+ if (!isset($click[$detail][$q])) {\r
+ $this->data['details'][] = $blank;\r
+ } else {\r
+ $difference = '';\r
+ if ($detail=='answers') {\r
+ if ($click[$detail][$q] != $clicks[$detail][$q]) {\r
+ $pattern = '/^'.preg_quote($clicks[$detail][$q], '/').',/';\r
+ $difference = preg_replace($pattern, '', $click[$detail][$q], 1);\r
+ }\r
+ } else { // hints, clues, checks\r
+ if ($click[$detail][$q] > $clicks[$detail][$q]) {\r
+ $difference = $click[$detail][$q] - $clicks[$detail][$q];\r
+ }\r
+ }\r
+ if ($difference) {\r
+ $clicks[$detail][$q] = $click[$detail][$q];\r
+ $click[$detail][$q] = $difference;\r
+ if ($detail=='answers') {\r
+ $this->set_legend($table, $q, $difference, $questions[$questionids[$q]]);\r
+ }\r
+ $this->data['details'][] = $difference;\r
+ $this->update_event_count($click, $detail, $q);\r
+ } else {\r
+ unset($click[$detail][$q]);\r
+ $this->data['details'][] = $blank;\r
+ }\r
+ }\r
+ }\r
+ break;\r
+ case 'changes':\r
+ case 'events':\r
+ if (empty($click[$detail][$q])) {\r
+ $this->data['details'][] = $blank;\r
+ } else {\r
+ $this->data['details'][] = $click[$detail][$q];\r
+ }\r
+ break;\r
+ default:\r
+ // do nothing\r
+ break;\r
+ } // end switch\r
+ } // for $q\r
+ } // foreach $detail\r
+ // set data cell values for\r
+ $this->set_data_click(\r
+ $allow_review ? '<a href="review.php?hp='.$hotpot->id.'&attempt='.$attempt->id.'">'.$clickcount.'</a>' : $clickcount,\r
+ trim(userdate($attempt->timefinish, $strftimetime)),\r
+ $exercisetype,\r
+ $click\r
+ );\r
+ $this->set_data($cells, 'click');\r
+ $this->set_data($cells, 'details');\r
+ $this->set_data_totals($click, $clicks, $questioncount, $blank, $attempt);\r
+ $this->set_data($cells, 'totals');\r
+ $table->data[] = $cells;\r
+ $clickcount++;\r
+ } // end foreach $attempt\r
+ // insert 'tabledivider' between users\r
+ $table->data[] = 'hr';\r
+ } // end foreach $user\r
+ // remove final 'hr' from data rows\r
+ array_pop($table->data);\r
+ if ($is_html && $CFG->hotpot_showtimes) {\r
+ $count = count($users);\r
+ $duration = sprintf("%0.3f", microtime_diff($start_report_time, microtime()));\r
+ print "$count users processed in $duration seconds (".sprintf("%0.3f", $duration/$count).' secs/user)<hr size="1" noshade="noshade" />'."\n";\r
+ }\r
+ $tables[] = &$table;\r
+ $this->create_legend_table($tables, $table);\r
+ } // end function\r
+ function get_exercisetype(&$questions, &$questionids, &$blank) {\r
+ if (empty($questions)) {\r
+ $type = $blank;\r
+ } else {\r
+ switch ($questions[$questionids[0]]->type) {\r
+ case HOTPOT_JCB:\r
+ $type = "JCB";\r
+ break;\r
+ case HOTPOT_JCLOZE :\r
+ $type = "JCloze";\r
+ break;\r
+ case HOTPOT_JCROSS :\r
+ $type = "JCross";\r
+ break;\r
+ case HOTPOT_JMATCH :\r
+ $type = "JMatch";\r
+ break;\r
+ case HOTPOT_JMIX :\r
+ $type = "JMix";\r
+ break;\r
+ case HOTPOT_JQUIZ :\r
+ $type = "JQuiz";\r
+ break;\r
+ case HOTPOT_TEXTOYS_RHUBARB :\r
+ $type = "Rhubarb";\r
+ break;\r
+ case HOTPOT_TEXTOYS_SEQUITUR :\r
+ $type = "Sequitur";\r
+ break;\r
+ default:\r
+ $type = $blank;\r
+ }\r
+ }\r
+ return $type;\r
+ }\r
+ function set_head(&$options, &$table, $zone, $exercisetype='', $details=array(), $questioncount=0) {\r
+ if (empty($table->head)) {\r
+ $table->head = array();\r
+ }\r
+ switch ($zone) {\r
+ case 'exercise':\r
+ array_push($table->head,\r
+ get_string('reportcoursename', 'hotpot'),\r
+ get_string('reportsectionnumber', 'hotpot'),\r
+ get_string('reportexercisenumber', 'hotpot'),\r
+ get_string('reportexercisename', 'hotpot'),\r
+ get_string('reportexercisetype', 'hotpot'),\r
+ get_string('reportnumberofquestions', 'hotpot')\r
+ );\r
+ break;\r
+ case 'user':\r
+ array_push($table->head,\r
+ get_string('reportstudentid', 'hotpot'),\r
+ get_string('reportlogindate', 'hotpot'),\r
+ get_string('reportlogintime', 'hotpot'),\r
+ get_string('reportlogofftime', 'hotpot')\r
+ );\r
+ break;\r
+ case 'attempt':\r
+ array_push($table->head,\r
+ get_string('reportattemptnumber', 'hotpot'),\r
+ get_string('reportattemptstart', 'hotpot'),\r
+ get_string('reportattemptfinish', 'hotpot')\r
+ );\r
+ break;\r
+ case 'click':\r
+ array_push($table->head,\r
+ get_string('reportclicknumber', 'hotpot'),\r
+ get_string('reportclicktime', 'hotpot'),\r
+ get_string('reportclicktype', 'hotpot')\r
+ );\r
+ break;\r
+ case 'details':\r
+ foreach($details as $detail) {\r
+ if ($exercisetype=='JQuiz' && $detail=='clues') {\r
+ $detail = 'showanswer';\r
+ }\r
+ $detail = get_string("report$detail", 'hotpot');\r
+ for ($i=0; $i<$questioncount; $i++) {\r
+ $str = get_string('questionshort', 'hotpot', $i+1);\r
+ if ($i==0 || $options['reportformat']!='htm') {\r
+ $str = "$detail $str";\r
+ }\r
+ $table->head[] = $str;\r
+ }\r
+ }\r
+ break;\r
+ case 'totals':\r
+ $reportpercentscore =get_string('reportpercentscore', 'hotpot');\r
+ if (!function_exists('clean_getstring_data')) { // Moodle 1.4 (and less)\r
+ $reportpercentscore = str_replace('%', '%%', $reportpercentscore);\r
+ }\r
+ array_push($table->head, \r
+ get_string('reportthisclick', 'hotpot', get_string('reportquestionstried', 'hotpot')),\r
+ get_string('reportsofar', 'hotpot', get_string('reportquestionstried', 'hotpot')),\r
+ get_string('reportthisclick', 'hotpot', get_string('reportright', 'hotpot')),\r
+ get_string('reportthisclick', 'hotpot', get_string('reportwrong', 'hotpot')),\r
+ get_string('reportthisclick', 'hotpot', get_string('reportnottried', 'hotpot')),\r
+ get_string('reportsofar', 'hotpot', get_string('reportright', 'hotpot')),\r
+ get_string('reportsofar', 'hotpot', get_string('reportwrong', 'hotpot')),\r
+ get_string('reportsofar', 'hotpot', get_string('reportnottried', 'hotpot')),\r
+ get_string('reportthisclick', 'hotpot', get_string('reportanswers', 'hotpot')),\r
+ get_string('reportthisclick', 'hotpot', get_string('reporthints', 'hotpot')),\r
+ get_string('reportthisclick', 'hotpot', get_string($exercisetype=='JQuiz' ? 'reportshowanswer' : 'reportclues', 'hotpot')),\r
+ get_string('reportthisclick', 'hotpot', get_string('reportevents', 'hotpot')),\r
+ get_string('reportsofar', 'hotpot', get_string('reporthints', 'hotpot')),\r
+ get_string('reportsofar', 'hotpot', get_string($exercisetype=='JQuiz' ? 'reportshowanswer' : 'reportclues', 'hotpot')),\r
+ get_string('reportthisclick', 'hotpot', get_string('reportrawscore', 'hotpot')),\r
+ get_string('reportthisclick', 'hotpot', get_string('reportmaxscore', 'hotpot')),\r
+ get_string('reportthisclick', 'hotpot', $reportpercentscore),\r
+ get_string('reportsofar', 'hotpot', get_string('reportrawscore', 'hotpot')),\r
+ get_string('reportsofar', 'hotpot', get_string('reportmaxscore', 'hotpot')),\r
+ get_string('reportsofar', 'hotpot', $reportpercentscore),\r
+ get_string('reporthotpotscore', 'hotpot')\r
+ );\r
+ break;\r
+ } // end switch\r
+ }\r
+ function set_align_and_wrap(&$table) {\r
+ $count = count($table->head);\r
+ for ($i=0; $i<$count; $i++) {\r
+ if ($i==0 || $i==1 || $i==2 || $i==4 || $i==5 || $i>=7) {\r
+ // numeric (and short text) columns\r
+ $table->align[] = 'center';\r
+ $table->wrap[] = '';\r
+ } else {\r
+ // text columns\r
+ $table->align[] = 'left';\r
+ $table->wrap[] = 'nowrap';\r
+ }\r
+ }\r
+ }\r
+ function set_data_exercise(&$cm, &$course, &$hotpot, &$questions, &$questionids, &$questioncount, &$blank) {\r
+ // get exercise details (course name, section number, activity number, quiztype and question count)\r
+ $record = get_record("course_sections", "id", $cm->section);\r
+ $this->data['exercise'] = array(\r
+ 'course' => $course->shortname,\r
+ 'section' => empty($record) ? $blank : $record->section+1,\r
+ 'number' => empty($record) ? $blank : array_search($cm->id, explode(',', $record->sequence))+1,\r
+ 'name' => $hotpot->name,\r
+ 'type' => $this->get_exercisetype($questions, $questionids, $blank),\r
+ 'questioncount' => $questioncount\r
+ );\r
+ }\r
+ function set_data_user(&$options, &$course, &$user) {\r
+ global $CFG;\r
+ // shortcut to first attempt record (which also hold user info)\r
+ $attempt = &$user->attempts[0];\r
+ $idnumber = $attempt->idnumber;\r
+ if (empty($idnumber)) {\r
+ $idnumber = fullname($attempt);\r
+ }\r
+ if ($options['reportformat']=='htm') {\r
+ $idnumber = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$attempt->userid.'&course='.$course->id.'">'.$idnumber.'</a>';\r
+ }\r
+ $this->data['user'] = array(\r
+ 'idnumber' => $idnumber,\r
+ );\r
+ }\r
+ function set_data_attempt(&$attempt, &$strftimedate, &$strftimetime, &$blank) {\r
+ global $CFG;\r
+ $records = get_records_sql_menu("\r
+ SELECT userid, MAX(time) AS logintime\r
+ FROM {$CFG->prefix}log\r
+ WHERE userid=$attempt->userid AND action='login' AND time<$attempt->timestart\r
+ GROUP BY userid\r
+ ");\r
+ if (empty($records)) {\r
+ $logindate = $blank;\r
+ $logintime = $blank;\r
+ } else {\r
+ $logintime = $records[$attempt->userid];\r
+ $logindate = trim(userdate($logintime, $strftimedate));\r
+ $logintime = trim(userdate($logintime, $strftimetime));\r
+ }\r
+ $records = get_records_sql_menu("\r
+ SELECT userid, MIN(time) AS logouttime\r
+ FROM {$CFG->prefix}log\r
+ WHERE userid=$attempt->userid AND action='logout' AND time>$attempt->cr_timefinish \r
+ GROUP BY userid\r
+ ");\r
+ if (empty($records)) {\r
+ $logouttime = $blank;\r
+ } else {\r
+ $logouttime = $records[$attempt->userid];\r
+ $logouttime = trim(userdate($logouttime, $strftimetime));\r
+ }\r
+ $this->data['attempt'] = array(\r
+ 'logindate' => $logindate,\r
+ 'logintime' => $logintime,\r
+ 'logouttime' => $logouttime,\r
+ 'number' => $attempt->attempt,\r
+ 'start' => trim(userdate($attempt->timestart, $strftimetime)),\r
+ 'finish' => trim(userdate($attempt->cr_timefinish, $strftimetime)),\r
+ );\r
+ }\r
+ function set_data_click($number, $time, $exercisetype, $click) {\r
+ $types = array();\r
+ foreach (array_keys($click['types']) as $type) {\r
+ if ($exercisetype=='JQuiz' && $type=='clues') {\r
+ $type = 'showanswer';\r
+ } else {\r
+ // remove final 's'\r
+ $type = substr($type, 0, strlen($type)-1);\r
+ }\r
+ // $types[] = get_string($type, 'hotpot');\r
+ $types[] = $type;\r
+ }\r
+ $this->data['click'] = array(\r
+ 'number' => $number,\r
+ 'time' => $time,\r
+ 'type' => empty($types) ? '??' : implode(',', $types)\r
+ );\r
+ }\r
+ function set_data_totals(&$click, &$clicks, &$questioncount, &$blank, &$attempt) {\r
+ $count= array(\r
+ 'click' => array(\r
+ 'correct' => count($click['correct']),\r
+ 'wrong' => count($click['wrong']),\r
+ 'answers' => count($click['answers']),\r
+ 'hints' => array_sum($click['hints']),\r
+ 'clues' => array_sum($click['clues']),\r
+ 'events' => array_sum($click['events']),\r
+ 'score' => array_sum($click['score']),\r
+ 'maxscore' => array_sum($click['weighting']),\r
+ ),\r
+ 'clicks' => array(\r
+ 'correct' => count($clicks['correct']),\r
+ 'wrong' => count($clicks['wrong']),\r
+ 'answers' => count($clicks['answers']),\r
+ 'hints' => array_sum($clicks['hints']),\r
+ 'clues' => array_sum($clicks['clues']),\r
+ 'score' => array_sum($clicks['score']),\r
+ 'maxscore' => array_sum($clicks['weighting']),\r
+ )\r
+ );\r
+ foreach ($count as $period=>$values) {\r
+ $count[$period]['nottried'] = $questioncount - ($values['correct'] + $values['wrong']);\r
+ $count[$period]['percent'] = empty($values['maxscore']) ? $blank : round(100 * $values['score'] / $values['maxscore'], 0);\r
+ // blank out zero click values\r
+ if ($period=='click') {\r
+ foreach ($values as $detail=>$value) {\r
+ if ($detail=='answers' || $detail=='hints' || $detail=='clues' || $detail=='events') {\r
+ if (empty($value)) {\r
+ $count[$period][$detail] = $blank;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ $this->data['totals'] = array(\r
+ $count['click']['answers'], // "q's tried"\r
+ $count['clicks']['answers'], // "q's tried so far"\r
+ $count['click']['correct'], // "right"\r
+ $count['click']['wrong'], // "wrong"\r
+ $count['click']['nottried'], // "not tried"\r
+ $count['clicks']['correct'], // "right so far"\r
+ $count['clicks']['wrong'], // "wrong so far"\r
+ $count['clicks']['nottried'], // "not tried so far"\r
+ $count['click']['answers'], // "answers",\r
+ $count['click']['hints'], // "hints",\r
+ $count['click']['clues'], // "clues",\r
+ $count['click']['events'], // "answers",\r
+ $count['clicks']['hints'], // "hints so far",\r
+ $count['clicks']['clues'], // "clues so far",\r
+ $count['click']['score'], // 'raw score',\r
+ $count['click']['maxscore'], // 'max score',\r
+ $count['click']['percent'], // '% score'\r
+ $count['clicks']['score'], // 'raw score,\r
+ $count['clicks']['maxscore'], // 'max score,\r
+ $count['clicks']['percent'], // '% score\r
+ $attempt->score // 'hotpot score'\r
+ );\r
+ }\r
+ function update_event_count(&$click, $detail, $q) {\r
+ if ($detail=='checks' || $detail=='hints' || $detail=='clues') {\r
+ $click['types'][$detail] = true;\r
+ }\r
+ if ($detail=='answers' || $detail=='hints' || $detail=='clues') {\r
+ $click['events'][$q] = isset($click['events'][$q]) ? $click['events'][$q]+1 : 1;\r
+ }\r
+ if ($detail=='answers') {\r
+ $click['changes'][$q] = isset($click['changes'][$q]) ? $click['changes'][$q]+1 : 1;\r
+ }\r
+ }\r
+ function set_data(&$cells, $zone) {\r
+ foreach ($this->data[$zone] as $name=>$value) {\r
+ $cells[] = $value;\r
+ }\r
+ }\r
+} // end class\r
+?>\r
-<?php // $Id$
-/// Overview report just displays a big table of all the attempts
-class hotpot_report extends hotpot_default_report {
- function display(&$hotpot, &$cm, &$course, &$users, &$attempts, &$questions, &$options) {
- $this->create_overview_table($hotpot, $cm, $course, $users, $attempts, $questions, $options, $tables=array());
- $this->print_report($course, $hotpot, $tables, $options);
- return true;
- }
- function create_overview_table(&$hotpot, &$cm, &$course, &$users, &$attempts, &$questions, &$options, &$tables) {
- global $CFG;
- $strtimeformat = get_string('strftimedatetime');
- $is_html = ($options['reportformat']=='htm');
- $spacer = $is_html ? ' ' : ' ';
- $br = $is_html ? "<br />\n" : "\n";
- // initialize $table
- unset($table);
- $table->border = 1;
- $table->width = 10;
- $table->head = array();
- $table->align = array();
- $table->size = array();
- $table->wrap = array();
- // picture column, if required
- if ($is_html) {
- $table->head[] = $spacer;
- $table->align[] = 'center';
- $table->size[] = 10;
- $table->wrap[] = "nowrap";
- }
- array_push($table->head,
- get_string("name"),
- hotpot_grade_heading($hotpot, $options),
- get_string("attempt", "quiz"),
- get_string("time", "quiz"),
- get_string("reportstatus", "hotpot"),
- get_string("timetaken", "quiz"),
- get_string("score", "quiz")
- );
- array_push($table->align, "left", "center", "center", "left", "center", "center", "center");
- array_push($table->wrap, "nowrap", "nowrap", "nowrap", "nowrap", "nowrap", "nowrap", "nowrap");
- array_push($table->size, "*", "*", "*", "*", "*", "*", "*");
- $abandoned = 0;
- foreach ($users as $user) {
- // shortcut to user info held in first attempt record
- $u = &$user->attempts[0];
- $picture = '';
- $name = fullname($u);
- if ($is_html) {
- $picture = print_user_picture($u->userid, $course->id, $u->picture, false, true);
- $name = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$u->userid.'&course='.$course->id.'">'.$name.'</a>';
- }
- $grade = isset($user->grade) ? $user->grade : $spacer;
- $attemptcount = count($user->attempts);
- if ($attemptcount>1) {
- $text = $name;
- $name = NULL;
- $name->text = $text;
- $name->rowspan = $attemptcount;
- $text = $grade;
- $grade = NULL;
- $grade->text = $text;
- $grade->rowspan = $attemptcount;
- }
- $data = array();
- if ($is_html) {
- if ($attemptcount>1) {
- $text = $picture;
- $picture = NULL;
- $picture->text = $text;
- $picture->rowspan = $attemptcount;
- }
- $data[] = $picture;
- }
- array_push($data, $name, $grade);
- foreach ($user->attempts as $attempt) {
- // increment count of abandoned attempts
- // if attempt is marked as finished but has no score
- if ($attempt->status==HOTPOT_STATUS_ABANDONED) {
- $abandoned++;
- }
- $attemptnumber = $attempt->attempt;
- $starttime = trim(userdate($attempt->timestart, $strtimeformat));
- if ($is_html && isset($attempt->score) && (isteacher($course->id) || $hotpot->review)) {
- $attemptnumber = '<a href="review.php?hp='.$hotpot->id.'&attempt='.$attempt->id.'">'.$attemptnumber.'</a>';
- $starttime = '<a href="review.php?hp='.$hotpot->id.'&attempt='.$attempt->id.'">'.$starttime.'</a>';
- }
- if ($is_html && isteacher($course->id)) {
- $checkbox = '<input type=checkbox name="box'.$attempt->clickreportid.'" value="'.$attempt->clickreportid.'">'.$spacer;
- } else {
- $checkbox = '';
- }
- $timetaken = empty($attempt->timefinish) ? $spacer : format_time($attempt->timefinish - $attempt->timestart);
- $score = hotpot_format_score($attempt);
- if ($is_html && is_numeric($score) && $score==$user->grade) { // best grade
- $score = '<span class="highlight">'.$score.'</span>';
- }
- array_push($data,
- $attemptnumber,
- $checkbox.$starttime,
- hotpot_format_status($attempt),
- $timetaken,
- $score
- );
- $table->data[] = $data;
- $data = array();
- } // end foreach $attempt
- $table->data[] = 'hr';
- } // end foreach $user
- // remove final 'hr' from data rows
- array_pop($table->data);
- // add the "delete" form to the table
- if ($options['reportformat']=='htm' && isteacher($course->id)) {
- $strdeletecheck = get_string('deleteattemptcheck','quiz');
- $table->start = $this->deleteform_javascript();
- $table->start .= '<form method="post" action="report.php" name="deleteform" onsubmit="'."return deletecheck('".$strdeletecheck."', 'selection')".'">'."\n";
- $table->start .= '<input type="hidden" name="del" value="selection">'."\n";
- $table->start .= '<input type="hidden" name="id" value="'.$cm->id.'">'."\n";
- $table->finish = '<center>'."\n";
- $table->finish .= '<input type="submit" value="'.get_string("deleteselected").'"> '."\n";
- if ($abandoned) {
- $table->finish .= '<input type=button value="'.get_string('deleteabandoned', 'hotpot').'" onClick="if(deletecheck('."'".addslashes(get_string('deleteabandonedcheck', 'hotpot', $abandoned))."', 'abandoned', true".'))document.deleteform.submit();">'."\n";
- }
- $table->finish .= '<input type=button value="'.get_string("deleteall").'" onClick="if(deletecheck('."'".addslashes($strdeletecheck)."', 'all', true".'))document.deleteform.submit();">'."\n";
- $table->finish .= '</center>'."\n";
- $table->finish .= '</form>'."\n";
- }
- $tables[] = &$table;
- }
- function deleteform_javascript() {
- $strselectattempt = addslashes(get_string('selectattempt','hotpot'));
- return <<<END_OF_JAVASCRIPT
-<script type="text/javascript">
-<!--
-function deletecheck(p, v, x) {
- var r = false; // result
- // get length of form elements
- var f = document.deleteform;
- var l = f ? f.elements.length : 0;
- // count selected items, if necessary
- if (!x) {
- x = 0;
- for (var i=0; i<l; i++) {
- var obj = f.elements[i];
- if (obj.type && obj.type=='checkbox' && obj.checked) {
- x++;
- }
- }
- }
- // confirm deletion
- var n = navigator;
- if (x || (n.appName=='Netscape' && parseint(n.appVersion)==2)) {
- r = confirm(p);
- if (r) {
- f.del.value = v;
- }
- } else {
- alert('$strselectattempt');
- }
- return r;
-}
-//-->
-</script>
-END_OF_JAVASCRIPT
-;
- } // end function
-} // end class
-?>
+<?php // $Id$\r
+/// Overview report just displays a big table of all the attempts\r
+class hotpot_report extends hotpot_default_report {\r
+\r
+ function display(&$hotpot, &$cm, &$course, &$users, &$attempts, &$questions, &$options) {\r
+ $tables = array();\r
+ $this->create_overview_table($hotpot, $cm, $course, $users, $attempts, $questions, $options, $tables);\r
+ $this->print_report($course, $hotpot, $tables, $options);\r
+ return true;\r
+ }\r
+ function create_overview_table(&$hotpot, &$cm, &$course, &$users, &$attempts, &$questions, &$options, &$tables) {\r
+ global $CFG;\r
+ $strtimeformat = get_string('strftimedatetime');\r
+ $is_html = ($options['reportformat']=='htm');\r
+ $spacer = $is_html ? ' ' : ' ';\r
+ $br = $is_html ? "<br />\n" : "\n";\r
+ // initialize $table\r
+ unset($table);\r
+ $table->border = 1;\r
+ $table->width = 10;\r
+ $table->head = array();\r
+ $table->align = array();\r
+ $table->size = array();\r
+ $table->wrap = array();\r
+ // picture column, if required\r
+ if ($is_html) {\r
+ $table->head[] = $spacer;\r
+ $table->align[] = 'center';\r
+ $table->size[] = 10;\r
+ $table->wrap[] = "nowrap";\r
+ }\r
+ array_push($table->head, \r
+ get_string("name"), \r
+ hotpot_grade_heading($hotpot, $options),\r
+ get_string("attempt", "quiz"), \r
+ get_string("time", "quiz"), \r
+ get_string("reportstatus", "hotpot"), \r
+ get_string("timetaken", "quiz"), \r
+ get_string("score", "quiz")\r
+ );\r
+ array_push($table->align, "left", "center", "center", "left", "center", "center", "center");\r
+ array_push($table->wrap, "nowrap", "nowrap", "nowrap", "nowrap", "nowrap", "nowrap", "nowrap");\r
+ array_push($table->size, "*", "*", "*", "*", "*", "*", "*");\r
+ $abandoned = 0;\r
+ foreach ($users as $user) {\r
+ // shortcut to user info held in first attempt record\r
+ $u = &$user->attempts[0];\r
+ $picture = '';\r
+ $name = fullname($u);\r
+ if ($is_html) {\r
+ $picture = print_user_picture($u->userid, $course->id, $u->picture, false, true);\r
+ $name = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$u->userid.'&course='.$course->id.'">'.$name.'</a>';\r
+ }\r
+ $grade = isset($user->grade) ? $user->grade : $spacer;\r
+ $attemptcount = count($user->attempts);\r
+ if ($attemptcount>1) {\r
+ $text = $name;\r
+ $name = NULL;\r
+ $name->text = $text;\r
+ $name->rowspan = $attemptcount;\r
+ $text = $grade;\r
+ $grade = NULL;\r
+ $grade->text = $text;\r
+ $grade->rowspan = $attemptcount;\r
+ }\r
+ $data = array();\r
+ if ($is_html) {\r
+ if ($attemptcount>1) {\r
+ $text = $picture;\r
+ $picture = NULL;\r
+ $picture->text = $text;\r
+ $picture->rowspan = $attemptcount;\r
+ }\r
+ $data[] = $picture;\r
+ }\r
+ array_push($data, $name, $grade);\r
+ foreach ($user->attempts as $attempt) {\r
+ // increment count of abandoned attempts\r
+ // if attempt is marked as finished but has no score\r
+ if ($attempt->status==HOTPOT_STATUS_ABANDONED) {\r
+ $abandoned++;\r
+ }\r
+ $attemptnumber = $attempt->attempt;\r
+ $starttime = trim(userdate($attempt->timestart, $strtimeformat));\r
+ if ($is_html && isset($attempt->score) && (isteacher($course->id) || $hotpot->review)) {\r
+ $attemptnumber = '<a href="review.php?hp='.$hotpot->id.'&attempt='.$attempt->id.'">'.$attemptnumber.'</a>';\r
+ $starttime = '<a href="review.php?hp='.$hotpot->id.'&attempt='.$attempt->id.'">'.$starttime.'</a>';\r
+ }\r
+ if ($is_html && isteacher($course->id)) {\r
+ $checkbox = '<input type=checkbox name="box'.$attempt->clickreportid.'" value="'.$attempt->clickreportid.'">'.$spacer;\r
+ } else {\r
+ $checkbox = '';\r
+ }\r
+ $timetaken = empty($attempt->timefinish) ? $spacer : format_time($attempt->timefinish - $attempt->timestart);\r
+ $score = hotpot_format_score($attempt);\r
+ if ($is_html && is_numeric($score) && $score==$user->grade) { // best grade\r
+ $score = '<span class="highlight">'.$score.'</span>';\r
+ }\r
+ array_push($data, \r
+ $attemptnumber,\r
+ $checkbox.$starttime,\r
+ hotpot_format_status($attempt),\r
+ $timetaken,\r
+ $score\r
+ );\r
+ $table->data[] = $data;\r
+ $data = array();\r
+ } // end foreach $attempt\r
+ $table->data[] = 'hr';\r
+ } // end foreach $user\r
+ // remove final 'hr' from data rows\r
+ array_pop($table->data);\r
+ // add the "delete" form to the table\r
+ if ($options['reportformat']=='htm' && isteacher($course->id)) {\r
+ $strdeletecheck = get_string('deleteattemptcheck','quiz');\r
+ $table->start = $this->deleteform_javascript();\r
+ $table->start .= '<form method="post" action="report.php" name="deleteform" onsubmit="'."return deletecheck('".$strdeletecheck."', 'selection')".'">'."\n";\r
+ $table->start .= '<input type="hidden" name="del" value="selection">'."\n";\r
+ $table->start .= '<input type="hidden" name="id" value="'.$cm->id.'">'."\n";\r
+ $table->finish = '<center>'."\n";\r
+ $table->finish .= '<input type="submit" value="'.get_string("deleteselected").'"> '."\n";\r
+ if ($abandoned) {\r
+ $table->finish .= '<input type=button value="'.get_string('deleteabandoned', 'hotpot').'" onClick="if(deletecheck('."'".addslashes(get_string('deleteabandonedcheck', 'hotpot', $abandoned))."', 'abandoned', true".'))document.deleteform.submit();">'."\n";\r
+ }\r
+ $table->finish .= '<input type=button value="'.get_string("deleteall").'" onClick="if(deletecheck('."'".addslashes($strdeletecheck)."', 'all', true".'))document.deleteform.submit();">'."\n";\r
+ $table->finish .= '</center>'."\n";\r
+ $table->finish .= '</form>'."\n";\r
+ }\r
+ $tables[] = &$table;\r
+ }\r
+ function deleteform_javascript() {\r
+ $strselectattempt = addslashes(get_string('selectattempt','hotpot'));\r
+ return <<<END_OF_JAVASCRIPT\r
+<script type="text/javascript">\r
+<!--\r
+function deletecheck(p, v, x) {\r
+ var r = false; // result\r
+ // get length of form elements\r
+ var f = document.deleteform;\r
+ var l = f ? f.elements.length : 0;\r
+ // count selected items, if necessary\r
+ if (!x) {\r
+ x = 0;\r
+ for (var i=0; i<l; i++) {\r
+ var obj = f.elements[i];\r
+ if (obj.type && obj.type=='checkbox' && obj.checked) {\r
+ x++;\r
+ }\r
+ }\r
+ }\r
+ // confirm deletion\r
+ var n = navigator;\r
+ if (x || (n.appName=='Netscape' && parseint(n.appVersion)==2)) {\r
+ r = confirm(p);\r
+ if (r) {\r
+ f.del.value = v;\r
+ }\r
+ } else {\r
+ alert('$strselectattempt');\r
+ }\r
+ return r;\r
+}\r
+//-->\r
+</script>\r
+END_OF_JAVASCRIPT\r
+;\r
+ } // end function\r
+} // end class\r
+?>\r