From: moodler Date: Thu, 20 Nov 2003 16:02:13 +0000 (+0000) Subject: New report from Thomas Robb - provides detailed statistics. Needs some work. X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=565e970ee212aa5a355890ff85a14828b4bf735a;p=moodle.git New report from Thomas Robb - provides detailed statistics. Needs some work. --- diff --git a/mod/quiz/report/fullstat/report.php b/mod/quiz/report/fullstat/report.php new file mode 100755 index 0000000000..ceccd02134 --- /dev/null +++ b/mod/quiz/report/fullstat/report.php @@ -0,0 +1,859 @@ +id; + $qs_in_order =qr_getqs($thisquizid); + $qcount = 0; + $max_choices = 0; //for printing tallies we need to know how many rows to print + $table_colcount = 0; + foreach ($qs_in_order as $qid){ + $table_colcount++; + //Get the question type and text and append to object + $question_data = get_records_select("quiz_questions",$select="id='$qid'","","qtype,questiontext"); + foreach($question_data as $thiskey => $thisq){ + $quests[$qid]["qtype"] = $thiskey; + $quests[$qid]["qtext"] = $question_data[$thiskey]->questiontext; + } + if($quests[$qid][qtype] == 5){ + //for MATCH items we need to know how many items there are + $thismatch = get_record("quiz_match","question","$qid"); + $temparray = explode(",",$thismatch->subquestions); + $match_number[$qid] = count($temparray); + $match_start[$qid] = $temparray[0]; + $table_colcount = $table_colcount + $match_number[$qid] - 1; + } + $choice_data = get_records_select("quiz_answers",$select="question='$qid'","","id as cid,answer,fraction"); + if($quests[$qid][qtype] == 8){ + $thismin[$qid] = get_field("quiz_numerical","min","question","$qid"); + $thismax[$qid] = get_field("quiz_numerical","max","question","$qid"); + $quests[$qid]["correct"] = $thismin[$qid] ."< $choice_data->answer >" . $thismax[$qid]; + } + if($quests[$qid][qtype] >3) {continue;} + //only get choices here if type is SHORTANSWER,TRUEFALSE or MULTICHOICE + //Get the choices for each question and add to object[choice] each choicd ID and text + $choice_count=0; + foreach($choice_data as $thiscid=>$thischoice){ + $choice_count++; + $quests[$qid]["choice"]["$thiscid"]["answer"] = $thischoice->answer; + $quests[$qid]["choice"]["$thiscid"]["choiceno"] = $choice_count; + //if the fraction = 1, then set this choice number as the correct answer + if ($thischoice->fraction == 1){ + //append answer if more than one + if($quests[$qid]["correct"]){ + $quests[$qid]["correct"] .= "," . $thischoice->answer; + } else { + if($quests[$qid][qtype] == 3) { + $quests[$qid]["correct"] = $choice_count; + } else { + $quests[$qid]["correct"] = $thischoice->answer; + } + } + } + } + } +if($debug and !$download){ +print("

Quests

"); +print_object($quests); +} + $user_resps = qr_quiz_responses($thisquizid); +// //print_object($user_resps); + foreach($user_resps as $thiskey => $thisresp){ + $userdata[$thisresp->userid][$thisresp->attemptno]['response'][$thisresp->question]=$thisresp->answer; + $userdata[$thisresp->userid][$thisresp->attemptno]['grade']=$thisresp->sumgrades; + $userdata[$thisresp->userid][$thisresp->attemptno]['name']=$thisresp->lastname . ", " . $thisresp->firstname; + $userdata[$thisresp->userid][$thisresp->attemptno][attemptid]=$thisresp->aid; + } +if($debug and !$download){ +print("

User Data

"); +print_object($userdata); +} + //now go through $userdata and create tally by user, attempt, question storing both response and if correct + $reportline = 0; + foreach($userdata as $thisuser){ + foreach($thisuser as $thiskey=>$thisattempt){ +// //print_object($thisattempt); + $reportline++; + $data_tally[$reportline][$thisattempt[attemptid]][] = $thisattempt[name]; + $data_tally[$reportline][$thisattempt[attemptid]][] = $thisattempt[grade]; //raw grade needs to be divided by total grades possible + //now for each question, record response as it should be printed and whether right, wrong or skipped + //SHORTASNSWER the answer as in $userdata; TF or MULTI need response looked by from cid from $quests + //MATCH needs elaborate processing + //We need to go through the responses in the order Qs presented thus the use of $qs_in_order not just $thisattempt + foreach ($qs_in_order as $qid){ + $thisanswer = $thisattempt[response][$qid]; + if($quests[$qid][qtype]==5) { + //for MATCH processing. Treat each match couplet as an item for $data_tally + //builds an array of all questions and answers for match questions + $quiz_matches = qr_match_array($qid); + $matchsets = explode(",",$thisanswer); + //sort needed so that same items line up vertically + sort($matchsets); + $matchcnt = 0; + foreach($matchsets as $thisset){ + $matchcnt++; + $nowpair = explode("-",$thisset); + $phrasepair[0] = $quiz_matches[$nowpair[0]][Q]; + $phrasepair[1] = $quiz_matches[$nowpair[1]][A]; + //$match_answers keeps the correct answers for use in Response Analysis + //This will operate redundantly for each user but better than setting up separate routine to run once(?) + $match_answers[$qid][$nowpair[0]] = $phrasepair[1]; + $match_qs[$qid][$nowpair[0]] = $phrasepair[0]; + $rid = $nowpair[1]; + $qtally[$qid][$nowpair[0]][$nowpair[1]][tally]++; + $qtally[$qid][$nowpair[0]][$nowpair[1]][answer] = $phrasepair[1]; + if ($quiz_matches[$nowpair[0]] == $quiz_matches[$nowpair[1]]) { + $pairdata[score] = 1; + $qtally[$qid][$nowpair[0]][correct]++; + } else { + $pairdata[score] = 0; + } + $pairdata[data] = $phrasepair; + $pairdata[qtype] = 5; + $pairdata[qid] = $qid; + $data_tally[$reportline][$thisattempt[attemptid]][] = $pairdata; + } + } elseif ($quests[$qid][qtype]==8) { + $thisdata = qr_answer_lookup($qid,$thisanswer); + $data_tally[$reportline][$thisattempt[attemptid]][] = $thisdata; + } else { + $thisdata = qr_answer_lookup($qid,$thisanswer); + //$thisdata returns couplet of display string and right/wrong + if(!$thisdata[data]) {$thisdata[data] = "--";} + if($thisdata) { + $data_tally[$reportline][$thisattempt[attemptid]][] = $thisdata; + } + } + } + } + } +$total_user_count = $reportline; + //prepare headers (must do now because $table_colcount calculated here +if($debug and !$download){ +print("

Data Tally

"); +print_object($data_tally); +} + //Create here an array with the response analysis data for use with both screen display & Excel + // 2 dimensional array has as many cells across as items + title, as many down as $max_choices + // plus one row [0] for correct items + // Populate array first with "--" in each cell + $analysis[] = "--"; + $analysis0 = array_pad($analysis,$table_colcount+1,"--"); + for ($i = 1; $i <= $max_choices+1; $i++){ + $analysis[$i] = $analysis0; + } + + $pct_correct = qr_make_footers(); + +if($debug and !$download){ +print("

Footers

"); +print_object($pct_correct); +} +// + //display a row for each possible multiple choice with $max_choices being highest row + for ($i = 1; $i<= $max_choices;$i++){ + //prepare answer tallies + //2 columns already spoken for + $current_column = 0; + foreach ($qs_in_order as $qid){ + $current_column++; + switch ($quests[$qid][qtype]) { + case 1: + if(!$sa_tally[$qid]){ + $sa_tally[$qid] = qr_make_satally($qid,$current_column); + } + break; + case 2: + if(!$tf_tally[$qid]){ + $tf_tally[$qid] = qr_make_tftally($qid,$current_column); + } + break; + case 3: + if($qtally[$qid][$i]){ + $analysis[$i][$current_column] = $qtally[$qid][$i]; + } + break; + case 8: + if(!$num_tally[$qid]){ + $num_tally[$qid] = qr_make_numtally($qid,$current_column); + } + break; + case 5: + //Make the inverted array if not already made + if(! $match_tally[$qid]){ + $match_tally[$qid] = qr_make_matchtally($qid); + } + $match_end = $match_start[$qid] + $match_number[$qid] -1; + $colcounter = 0; + for ($j = $match_start[$qid];$j <= $match_end;$j++){ + $colcounter++; + if($match_tally[$qid][$i][$colcounter]) { + $tallytext = $match_tally[$qid][$i][$colcounter][answer]; + $tallycount = $match_tally[$qid][$i][$colcounter][tally]; + //Two slashes used to represent location of a break since one slash might appear in data + $analysis[$i][$current_column + $colcounter-1] = $tallytext . "//" . $tallycount ; + } + } + $current_column += $match_number[$qid] -1; + break; + default: + + break; + } + } + } + +if($debug and !$download){ +print("

Analysis

"); +print_object($analysis); +} + /// If spreadsheet is wanted, produce one + if ($download == "xls") { + require_once("$CFG->libdir/excel/Worksheet.php"); + require_once("$CFG->libdir/excel/Workbook.php"); + + header("Content-type: application/vnd.ms-excel"); + header("Content-Disposition: attachment; filename=$course->shortname ".$quiz->name.".xls"); + header("Expires: 0"); + header("Cache-Control: must-revalidate, post-check=0,pre-check=0"); + header("Pragma: public"); + $workbook = new Workbook("-"); + // Creating the first worksheet + $myxls = &$workbook->add_worksheet('Responses for each student'); + + + /// format types + $format =& $workbook->add_format(); + $format->set_bold(0); + $formaty =& $workbook->add_format(); + $formaty->set_bg_color('yellow'); + $formatyc =& $workbook->add_format(); + $formatyc->set_bg_color('yellow'); //bold text on yellow bg + $formatyc->set_bold(1); + $formatyc->set_align('center'); + $formatc =& $workbook->add_format(); + $formatc->set_align('center'); + $formatb =& $workbook->add_format(); + $formatb->set_bold(1); + $formatbc =& $workbook->add_format(); + $formatbc->set_bold(1); + $formatbc->set_align('center'); + $formatbrt =& $workbook->add_format(); + $formatbrt->set_bold(1); + $formatbrt->set_align('right'); + $formatred =& $workbook->add_format(); + $formatred->set_bold(1); + $formatred->set_color('red'); + $formatred->set_align('center'); + $formatblue =& $workbook->add_format(); + $formatblue->set_bold(1); + $formatblue->set_color('blue'); + $formatblue->set_align('center'); + $myxls->write_string(0,0,$quiz->name); + $myxls->set_column(0,0,25); + $row=2; + $qcount=0; +// $myxls->write_string(0,2,$choiceMax,$formatyc); + //You might expect the headers to be written at this point, but we are saving it till last + $highest_Q_no = 0; + $totcolcount = $table_colcount+2; + $myxls->write_string(0,2,"Responses of Individuals to Each Item",$formatyc); +// qr_xls_headers("Name","Grade"); +//This should have been a function but there is an 'incurable' error: +// "Call to a member function on a non-object" It is repeated below for the 2nd worksheet with +// only minor variations + $nm = "Name";$Item="Grade"; + $row = 1; + $col = 0; + $qcount = 0; + $myxls->write_string($row,$col,$nm,$formatbc); + if($Item == "Grade") { + $col++; + $myxls->write_string($row,$col,$Item,$formatbc); + } + foreach($qs_in_order as $qid){ + $qcount++; + $col++; + if($quests[$qid][qtype] == 5) { + $i = 0; + foreach ($match_qs[$qid] as $nowq){ + $i++; + $qm = "Q-$qcount M-$i"; + $myxls->write_string($row,$col,$qm,$formatbc); + $myxls->write_string(2,$col,$nowq,$formatyc); + $col++; + } + $col--; + } else { + $myxls->write_string($row,$col,"Q-$qcount",$formatbc); + } + } + + //now print the lines of answers + + $row = 2; + foreach ($data_tally as $thisuserno=>$thisuser){ + foreach($thisuser as $thisattemptno=>$thisattempt){ + $row++; + foreach($thisattempt as $thisitemkey=>$thisitem) { + //$thisitemkeys 1 & 2 are name and total score + //There needs to be a 3-way branch, keys0 & 1 just print $thisitem + //else if $thisitem[qtype] = 5, then processing for MATCH is needed + //else the data to be printed is in $thisitem[data] and + //$thisitem[score] == 1 shows that the item was correct + if ($thisitem[score] < 1) {$thiscolor = $formatred;} else {$thiscolor = $formatblue;} + $col++; + if ($thisitemkey == 0){ + $col = 0; + $myxls->write_string($row,$col,$thisitem,$formatb); + } elseif ($thisitemkey == 1){ + $myxls->write_number($row,$col,$thisitem,$formatb); + } elseif ($thisitemkey[qtype] == 2){ + $myxls->write_string($row,$col,$thisitem[data][answer],$thiscolor); + } elseif ($thisitem[qtype] == 5) { + if ($thisitem[score] == 1) {$thiscolor = $formatblue;} else {$thiscolor = $formatred;} + if(!$thisitem[data][1]){$thisitem[data][1]="(No Response)";} +// $myxls->write_string(2,$col,$thisitem[data][0],$formatb); + $myxls->write_string($row,$col,$thisitem[data][1],$thiscolor); + } else { + $myxls->write_string($row,$col,$thisitem[data],$thiscolor); + } + } + } + } +// } + $myxls = &$workbook->add_worksheet('Item Response Analysis'); + $sheettitle = "Item Response Analysis"; + $myxls->write_string(0,0,$sheettitle,$formatb); + $itemcount = 0; + $nm = "Question"; + $row = 1; + $col = 0; + $qcount = 0; + $myxls->write_string($row,$col,$nm,$formatbc); + foreach($qs_in_order as $qid){ + $qcount++; + $col++; + if($quests[$qid][qtype] == 5) { + $i = 0; + foreach ($match_qs[$qid] as $nowq){ + $i++; + $qm = "Q-$qcount M-$i"; + $myxls->write_string($row,$col,$qm,$formatbc); + $myxls->write_string($row+1,$col,$nowq,$formatbc); + $col++; + } + $col--; + } else { + $myxls->write_string($row,$col,"Q-$qcount",$formatbc); + } + } + +// Now write tally data + $row = $row+2; + $myxls->write_string($row,1,"Correct Response:",$formatbc); + $col=1; + foreach ($qs_in_order as $qid){ + $col++; + if ($quests[$qid][qtype] == 5) { + foreach($match_answers[$qid] as $thisans){ + $myxls->write_string($row,1,$thisans,$formatbc); + $col++; + } + $col--; + } else { + $myxls->write_string($row,1,$quests[$qid][correct],$formatbc); + } + } + //display a row for each possible multiple choice with $max_choices being highest row,$table_colcount is the width + for ($i = 1; $i<= $max_choices;$i++){ + $label="M/C #$i"; + $myxls->write_string($row,0,$label,$formatbrt); + //display answer tallies + for ($j = 1; $j <= $table_colcount; $j++){ + //substitute "
" for a "//" + $nowdata = $analysis[$i][$j]; + if($slashpos = strpos($nowdata,"//")){ + $text = substr($nowdata,0,$slashpos); + $value = substr($nowdata,$slashpos+2); + $myxls->write_string($row,$j,$text,$formatc); + $myxls->write_string($row+1,$j,$value,$formatbc); + } else { + $myxls->write_string($row,$j,$nowdata,$formatc); + } + } + $row = $row+2; + } + + //Finally output the total percent correct + $row++; + $myxls->write_string($row,1,"Percent Correct:",$formatbrt); + for ($i = 1; $i<= $table_colcount;$i++){ + $myxls->write_string($row,$i,$pct_correct[$i],$formatbc); + } + + //Print the questions with responses on a new worksheet + $myxls = &$workbook->add_worksheet('Questions and Responses'); + $sheettitle = "Questions and Responses"; + $myxls->write_string(0,0,$sheettitle,$formatb); + $itemcount = 0; + //Now printout the questions (and M/C answers if $containsMC + + $qcount = 0; + $row = 1; + foreach ($qs_in_order as $qid){ + $row++; + $qcount++; + $label = "Q-$qcount"; + $myxls->write_string($row,0,$label,$formatb); + $myxls->write_string($row,1,$quests[$qid][qtext],$formatb); + $itemcount = 0; + if($quests[$qid][qtype]==3){ + $nowchoices = $quests[$qid][choice]; + foreach($nowchoices as $thischoice){ + $row++; + $label = "A-$thischoice[choiceno]"; + $myxls->write_string($row,2,$label,$formatb); + $myxls->write_string($row,3,$thischoice[answer],$formatb); + } + } + } + + $workbook->close(); + exit; + } + +////////--------------------------- + /// If a text file is wanted, produce one + if ($download == "txt") { + /// Print header to force download + + header("Content-Type: application/download\n"); + header("Content-Disposition: attachment; filename=\"$course->shortname $quiz->name.txt\""); + header("Expires: 0"); + header("Cache-Control: must-revalidate, post-check=0,pre-check=0"); + header("Pragma: public"); + + /// Print names of all the fields + + echo "$quiz->name"; + echo "\n"; + + /// Print all the user data + $colcount = count($question_ids); + foreach ($data_tally as $thisuserno=>$thisuser){ + foreach($thisuser as $thisattemptno=>$thisattempt){ + foreach($thisattempt as $thisitemkey=>$thisitem) { + if ($thisitem[score] < 1) {$mark = "";} else {$mark = "*";} + //First two items are name & grade + if ($thisitemkey < 2){ + echo $thisitem . "\t"; + } elseif ($thisitemkey[qtype] == 2){ + echo $thisitem[data][answer] . "\t"; + } elseif ($thisitem[qtype] == 5) { + if ($thisitem[score] == 1) {$mark = "*";} else {$mark="";} + if(!$thisitem[data][1]){$thisitem[data][1]="(No Response)";} + echo "{$thisitem[data][0]} -- $mark{$thisitem[data][1]}\t"; + } else { + echo "$mark{$thisitem[data]}\t"; + } + } + } + echo " \n"; + } + echo " \n"; + echo "* Asterisk indicates correct response"; + echo " \n"; + //Question numbers + for ($i = 1;$i <= $colcount;$i++) { + echo "Q-$i\t"; + } + echo " \n"; + //Q numbers + foreach($qs_in_order as $qid){ + $qcount++; + if($quests[$qid][qtype] == 5) { + $i = 0; + foreach ($match_qs[$qid] as $nowq){ + $i++; + echo "Q-$qcount M-$i\t"; + } + } else { + echo "Q-$qcount\t"; + } + } + echo " \n"; + //Repeat for q answers + foreach($qs_in_order as $qid){ + $qcount++; + if($quests[$qid][qtype] == 5) { + foreach ($match_qs[$qid] as $nowq){ + echo $nowq . "\t"; + } + } else { + echo "\t"; + } + } + echo " \n"; + + for ($i = 1; $i<= $max_choices;$i++){ + echo "M/C #$i\t"; + //display answer tallies + for ($j = 1; $j <= $table_colcount; $j++){ + //substitute "
" for a "//" + $nowdata = $analysis[$i][$j]; + if (strpos($nowdata,"//")>0) { + $nowdata = str_replace("//"," : ",$nowdata); + } + echo $nowdata . "\t"; + } + echo " \n"; + } + exit; + } +////////--------------------------- If it falls through both of the $download choices, print on screen + //Print user responses + print ("\n"); + $totcolcount = $table_colcount+2; + print(""); + qr_print_headers($data_tally,"Name","Grade"); + //now print the lines of answers + foreach ($data_tally as $thisuserno=>$thisuser){ + foreach($thisuser as $thisattemptno=>$thisattempt){ + print(""); + foreach($thisattempt as $thisitemkey=>$thisitem) { + //$thisitemkeys 1 & 2 are name and total score + //There needs to be a 3-way branch, keys0 & 1 just print $thisitem + //else if $thisitem[qtype] = 5, then processing for MATCH is needed + //else the data to be printed is in $thisitem[data] and $thisitem[score] == 1 shows that the item was correct + if ($thisitem[score] < 1) {$thiscolor = "ff0000";} else {$thiscolor = "000000";} + if ($thisitemkey == 0){ + print(""); + } elseif ($thisitemkey[qtype] == 2){ + print(""); + } elseif ($thisitem[qtype] == 5) { + if ($thisitem[score] == 1) {$thiscolor = "blue";} + if(!$thisitem[data][1]){$thisitem[data][1]="(No Response)";} + print(""); + } else { + print(""); + } + } + } + print("\n"); + } + +if($debug and !$download){ +print("

Qtally

"); +print_object($qtally); +} + //print tally of how many selected each choice + print(""); + qr_print_headers($data_tally,"Item"," "); + //display row with correct answers + print(""); + foreach ($qs_in_order as $qid){ + if ($quests[$qid][qtype] == 5) { + foreach($match_answers[$qid] as $thisans){ + print(""); + } + } else { + print(""); + } + } + print("\n"); + + //display a row for each possible multiple choice with $max_choices being highest row,$table_colcount is the width + for ($i = 1; $i<= $max_choices;$i++){ + print(""); + + } + } + print("\n"); + //Finally display the total percent correct + print(""); + for ($i = 0; $i< $table_colcount;$i++){ + print (" "); + } + print("\n"); + print("
Responses of Individuals to Each Item
$thisitem "); + } elseif ($thisitemkey == 1){ + print("  $thisitem    $thisitem[data][answer]  {$thisitem[data][0]}
{$thisitem[data][1]}
  {$thisitem[data]}  
Item Response Analysis
Correct Response: $thisans  {$quests[$qid][correct]} 
 M/C #$i"); + //display answer tallies + for ($j = 1; $j <= $table_colcount; $j++){ + //substitute "
" for a "//" + $nowdata = $analysis[$i][$j]; + if (strpos($nowdata,"//")>0) {$nowdata = str_replace("//","
",$nowdata);} + print("
 $nowdata
Percent Correct:{$pct_correct[$i]}
\n"); + + //Now printout the questions (and M/C answers if $containsMC + + print ("

\n"); + print("\n"); + $qcount = 0; + foreach ($qs_in_order as $qid){ + $qcount++; + print("\n"); + if($quests[$qid][qtype]==3){ + $nowchoices = $quests[$qid][choice]; + foreach($nowchoices as $thischoice){ + print(""); + print("\n"); + } + } + } + print("
QUIZ: $quiz->name   --   Listing of Items in This Quiz
Q-$qcount{$quests[$qid][qtext]}
 A-{$thischoice[choiceno]}{$thischoice[answer]}
\n"); + + echo "
\n"; + echo "\n"; + echo "
"; + unset($options); + $options["id"] = "$cm->id"; + $options["mode"] = "fullstat"; + $options["noheader"] = "yes"; + $options["download"] = "xls"; + print_single_button("report.php", $options, get_string("downloadexcel")); + echo ""; + $options["download"] = "txt"; + print_single_button("report.php", $options, get_string("downloadtext")); + echo "
"; +////////--------------------------- + return true; + } +} +////just functions below here---------------------------------------------- + +function qr_quiz_responses($quiz) { +// Given any quiz number, get all responses and place in +// $response object + global $CFG; + + $resp_recs =get_records_sql("SELECT r.id as rid, r.attempt, r.answer, r.question, a.attempt as attemptno, a.id as aid, a.quiz, a.userid, a.sumgrades, u.id as uid, u.lastname, u.firstname FROM {$CFG->prefix}quiz_responses r, {$CFG->prefix}quiz_attempts a, {$CFG->prefix}user u WHERE a.id = r.attempt AND a.quiz = '$quiz' AND a.userid = u.id ORDER BY u.lastname ASC, u.firstname ASC, r.id ASC"); + return $resp_recs; +} + +function qr_make_satally($qid,$col){ + global $analysis, $qtally,$max_choices; + $this_sa = $qtally[$qid][response]; + $rowcnt = 0; + if ($this_sa){ + foreach($this_sa as $thistext =>$thistally){ + $rowcnt++; + $analysis[$rowcnt][$col] = $thistext . "//" . $thistally; + } + } + if ($rowcnt > $max_choices) {$max_choices = $rowcnt;} + return 1; +} + +function qr_make_tftally($qid,$col){ + global $analysis, $qtally; + $this_tf = $qtally[$qid]; + foreach($this_tf as $thiskey=>$tallycnt){ + if ($thiskey == "True") { + $analysis[1][$col] = "True: " . $tallycnt; + } else if ($thiskey == "False") { + $analysis[2][$col] = "False: " . $tallycnt; + } + } + return 1; +} + +function qr_make_numtally($qid,$col){ + global $analysis, $qtally; + $this_num = $qtally[$qid]; + $rowcnt = 0; + if ($this_num){ + foreach($this_num[response] as $thisans=>$thistally){ + if($thisans){ + $rowcnt++; + $analysis[$rowcnt][$col] = $thisans . "//" . $thistally; + } + } + } + if ($rowcnt > $max_choices) {$max_choices = $rowcnt;} + return 1; +} + +function qr_make_matchtally($qid){ + //The MATCH items need to be inverted so that the 1st of each match can be printed in the first row, then the second, etc. + global $qtally; + $itemcntA = 0; + foreach ($qtally[$qid] as $thiskey=>$thisitem){ + if($thiskey != "correct"){ + $itemcntA++; + $itemcntB = 0; + if (gettype($thisitem) == "array"){ + foreach ($thisitem as $thisrid=>$thisans){ + if (!$thisans[answer]){continue;} + $itemcntB++; + $inverted[$itemcntB][$itemcntA][answer] = $thisans[answer]; + $inverted[$itemcntB][$itemcntA][tally] = $thisans[tally]; + } + } + } + } +return $inverted; +} + +function qr_print_headers($data_tally,$nm,$gd){ + global $qs_in_order,$qtally,$quests,$total_user_count,$match_number; + $qcount = 0; + if($nm == "Item") { + print("Question:"); + } else { + print("$nm$gd"); + } + foreach($qs_in_order as $qid){ + $qcount++; + if($quests[$qid][qtype] == 5) { + $colcount = $match_number[$qid]; + } else { + $colcount = 1; + } + print("Q-$qcount"); + } + print("\n"); +} + +function qr_make_footers(){ + //Create the percent correct for the footer + global $qs_in_order,$qtally,$quests,$total_user_count; + foreach($qs_in_order as $qid){ + if($quests[$qid][qtype] == 5) { + foreach ($qtally[$qid] as $thisitem){ + $this_correct = $thisitem[correct]; + $footers[] = qr_make_pct($this_correct); + } + } else { + $this_correct = $qtally[$qid][correct]; + $footers[] = qr_make_pct($this_correct); + } + } + return $footers; +} + +function qr_make_pct($this_correct){ + global $qs_in_order,$qtally,$quests,$total_user_count; + if($this_correct>0){ + $pct_cor =round(($this_correct/$total_user_count)*100,1); + } else { + $pct_cor = 0; + } + return $pct_cor ."%"; +} + +function qr_answer_lookup($qid,$thisanswer){ + //For each type of question, this needs to determine answer string to report and whether right or wrong + global $quests,$qtally,$max_choices,$thismin,$thismax; + $thistype = $quests[$qid][qtype]; + $returndata[data] = "--"; + $returndata[score] = 0; + $returndata[qtype] = $thistype; + $returndata[qid] = $qid; + $qtally[$qid][qtype] = $thistype; + switch ($thistype) { + case 1: //SHORTANSWER + $returndata[data] = $thisanswer; + $qtally[$qid][response][$thisanswer]++; + //convert all to lowercase to allow for mismatching cases to be correct + if (strpos(strtolower($quests[$qid][correct]),trim(strtolower($thisanswer))) >-1){ + $qtally[$qid][correct]++; + $returndata[score] = 1; + } + break; + case 2: //TRUEFALSE + $returndata[data] = $quests[$qid][choice][$thisanswer][answer]; + $qtally[$qid][$quests[$qid][choice][$thisanswer][answer]]++; + if ($quests[$qid][correct]==$quests[$qid][choice][$thisanswer][answer]){ + $returndata[score] = 1; + $qtally[$qid][correct]++; + } + break; + case 3: //MULTICHOICE + $returndata[data] = $quests[$qid][choice][$thisanswer][choiceno]; + if($max_choices < $returndata[data]) {$max_choices = $returndata[data];} + $qtally[$qid][$quests[$qid][choice][$thisanswer][choiceno]]++; + if (strtolower($quests[$qid][correct])==strtolower($quests[$qid][choice][$thisanswer][choiceno])){ + $returndata[score] = 1; + $qtally[$qid][correct]++; + } + break; + case 8: //NUMERICAL + $returndata[data] = $thisanswer; +// $returndata[data] = $thismin . "<" . $thisanswer . ">" . $thismax; + $qtally[$qid][response][$thisanswer]++; + if ($thisanswer >= $thismin[$qid] and $thisanswer <= $thismax[$qid]){ + $qtally[$qid][correct]++; + $returndata[score] = 1; + } + break; + } + return $returndata; +} + +function qr_getqs($quiz){ +// Returns a list of question numbers for a specific quiz + if (!$questions = get_record("quiz","id",$quiz)) { + notify("Could not find any questions for quiz $quiz"); + return false; + } + $qlist = array(); + $qlist = explode(",",$questions->questions); + return $qlist; +} + +function qr_match_array($nowQ){ + //builds an array of all questions and answers for match questions in the quiz for use in qr_match_table + global $quiz_matches,$quiz_match_hdrs; +//make an array of all Q & As for match questions +//format: $quiz_matches[quiz_match_sub_id][Q or A] + $allmatch = get_records("quiz_match_sub","question",$nowQ); +// //print_object($allmatch); + $hdrcnt=0; + foreach($allmatch as $thismatchitemno =>$thismatchitem){ + $hdrcnt++; + $quiz_matches[$thismatchitemno]["Q"] = $thismatchitem->questiontext; + $quiz_matches[$thismatchitemno]["A"] = $thismatchitem->answertext; + } + //needed so that we know how many column headers to create + $quiz_match_hdrs[$nowQ]=$hdrcnt; + return $quiz_matches; +} + +function qr_match_table($resplist){ + global $quiz_matches; + $tbl = "\n"; + $resp_array = explode(",",$resplist); + $q_cnt=0; + foreach ($resp_array as $resp_pair){ + $q_cnt++; + $tbl = $tbl .""; + } + $tbl = $tbl . "\n"; + foreach ($resp_array as $resp_pair){ + $resp_QA = explode("-",$resp_pair); + if ($resp_QA[0] == $resp_QA[1]){ + $qa = " {$quiz_matches[$resp_QA[0]]['Q']} - {$quiz_matches[$resp_QA[1]]['A']}"; + } else{ + $qa = " {$quiz_matches[$resp_QA[0]]['Q']} - {$quiz_matches[$resp_QA[1]]['A']}"; + } +// $qa = $resp_QA[0] . "=" . $resp_QA[1] ; + $tbl = $tbl . ""; + } + $tbl = $tbl . "\n
$q_cnt
$qa
\n"; + return $tbl; +} +?> \ No newline at end of file