#!/usr/bin/perl ## This file is profCourseRecData.pl ## It displays overall data on how students in various recitations ## are doing on problems. E.g. the instructor can spot difficult ## problems. ## #################################################################### # Copyright @ 1995-1998 University of Rochester # All Rights Reserved #################################################################### use lib '/ww/webwork/development/'; # mainWeBWorKDirectory; use strict; use Global; use Auth; use CGI qw(:standard); # Timing code use Benchmark; my $beginTime = new Benchmark; # end Timing code my %inputs; my ($classID, $setNumber,$User,$Session_key,$batchMode); &CGI::ReadParse; %inputs = %main::in; # get information from CGI inputs (see also below for additional information) $classID = $inputs{'course'}; $setNumber = $inputs{'setNo'}; $User = $inputs{'user'}; $Session_key = $inputs{'key'}; unless ($classID && $User && $Session_key) { &wwerror("$0","The script profCourseRecData.pl did not receive the proper input data.","","", query_string()); } # CAUTION: FOR THIS SCRIPT TO WORK CORRECTLTY, ALL STUDENTS # MUST HAVE BEEN ASSIGNED THE SAME NUMBER OF PROBLREMS # print "set is $setNumber"; # print "classID is $classID"; &getCourseEnvironment($classID); my $scriptDirectory = getWebworkScriptDirectory; my $databaseDirectory = getCourseDatabaseDirectory; my $templateDirectory = getCourseTemplateDirectory; my $cgiURL = getWebworkCgiURL; require "${scriptDirectory}$Global::DBglue_pl"; require "${scriptDirectory}$Global::FILE_pl"; require "${scriptDirectory}$Global::SCRtools_pl"; require "${scriptDirectory}$Global::HTMLglue_pl"; my $keyFile = &Global::getCourseKeyFile($classID); &verify_key($User, $Session_key, $keyFile, $classID); my $permissionsFile = &Global::getCoursePermissionsFile($classID); my $permissions = &get_permissions($User, $permissionsFile); if (($permissions != $Global::instructor_permissions) and ($permissions != $Global::TA_permissions) ) { print "permissions = $permissions instructor_permissions= $Global::instructor_permissions\n"; print &html_NO_PERMISSION; exit(0); } my $DELIM = $Global::delim; ## get rest of data from cgi form $batchMode = $inputs{'batchMode'}; ## if 1 it means user has choosen to ignore warning message # get list of problems and values from the database. Warn user if different students #have different numbers of problems or different valuse for the same problem my $cgiMode = 1; my ($warningMsg,$dueDate, $problemListref,$problemValueListref) = &readProblemsAndValuesFromDB($setNumber,0,$cgiMode,$batchMode); if ($warningMsg ne '') { &warningMsgPage(\%inputs,$warningMsg);} my @problemList = @$problemListref; my @problemValueList = @$problemValueListref; my $noOfProbs = @problemList; unshift @problemValueList, 0; ##off by 1 problem my (%NHash,%YHash,%attemptedProbHash); my (%totalScoreHash,%attemptedSetHash,%allStudentsHash); my $total_possible; my @recitationNameArray = &getAllClassRecitations($setNumber) ; my @excludedRecitationNameArray = (); @excludedRecitationNameArray = @Global::excluse_these_recitations_from_overall_statistics if defined @Global::excluse_these_recitations_from_overall_statistics; &processRecitationNameArrays(); ##separate included and excluded Recitations ## initialize hashes and load up data my $all = &uniqueCourseName(); &initializeAndLoadUp(\@recitationNameArray,$all); # begin printing HTML text print &htmlTOP("WeBWorK Course Data"); # print navigation buttons print qq! [Up]

!; print <

Current Statistics for set $setNumber in $classID

On this page, you can monitor the average progress of students for all recitations or by individual recitations. You can identify difficult problems by the percentage of students who have answered the problem correctly and/or by the average number of incorrect attempts per problem. All percentages and averages (except \% attempting) are based on the number of students who have attempted a set or problem, not on the total number of students in the recitation or course. Note that 50\% correct on a partial credit question could mean all students got half credit or half the students got full credit and half got no credit.

The first two tables do not contain data from "excluded" recitations. Excluded recitations typically contain practices uses, T.A.'s, prof's etc. Data for excluded recitations is displayed at the bottom of the page.

EOF ## create $dat arrays with the info. on average scores, etc my ($recitationName,$i, $dataRow,$item); my @dataArray =(); ## first row $dataRow = "recitations$DELIM \# of students$DELIM \% attempting set $setNumber$DELIM average score$DELIM possible score"; push @dataArray, $dataRow; ## display whole course data $dataRow = "$all $DELIM $allStudentsHash{$all} $DELIM"; ## all Recitations and total # of students $item =0; ## % of students who have attempted at least one problem in set $item = int(100*$attemptedSetHash{$all}/$allStudentsHash{$all}+.5) if $allStudentsHash{$all}; $dataRow .= "$item $DELIM"; $item =0; ## avg score of students who have attempted at least one problem in set $item = (int($totalScoreHash{$all} *10/$attemptedSetHash{$all}+.5))/10 if $attemptedSetHash{$all}; $item = sprintf '%.1f', $item; $dataRow .= "$item $DELIM"; $dataRow .= "$total_possible"; push @dataArray, $dataRow; ## display data for Recitations foreach $recitationName (@recitationNameArray) { $dataRow = "$recitationName $DELIM $allStudentsHash{$recitationName} $DELIM"; ## all recitations and total # of students $item =0; ## % of students who have attempted at least one problem in set $item = int(100*$attemptedSetHash{$recitationName}/$allStudentsHash{$recitationName}+.5) if $allStudentsHash{$recitationName}; $dataRow .= "$item $DELIM"; $item =0; ## avg score of students who have attempted at least one problem in set $item = (int($totalScoreHash{$recitationName} *10/$attemptedSetHash{$recitationName}+.5))/10 if $attemptedSetHash{$recitationName}; $item = sprintf '%.1f', $item; $dataRow .= "$item $DELIM"; $dataRow .= "$total_possible"; push @dataArray, $dataRow; } # print "

 @dataArray <\pre>";

print <

Overall Scores by recitation. $all is the total for all included recitations

EOF ## output the html table my $string = &delimitedArray2htmlTable(\@dataArray, 'htmltable'); print "${string}
"; ## now output the info on individaul problems ### display whole course data @dataArray =(); $dataRow = "$all $DELIM"; for ($i=1;$i<=$noOfProbs;$i++) { $dataRow .= "\# $i $DELIM"; } $dataRow =~ s|$DELIM$||; ## remove last \$DELIM push @dataArray, $dataRow; $dataRow = "\% attempting $DELIM"; for ($i=1;$i<=$noOfProbs;$i++) { $item =0; ## percent of students who have attempted this problem $item = int(100*$attemptedProbHash{$all}[$i]/$allStudentsHash{$all}+.5) if $allStudentsHash{$all}; $dataRow .= "$item $DELIM"; } $dataRow =~ s|$DELIM$||; ## remove last \$DELIM push @dataArray, $dataRow; $dataRow = "percent correct $DELIM"; ## all recitations and total # of students for ($i=1;$i<=$noOfProbs;$i++) { $item =0; ## % of students who have attempted this problem $item = int(100*$YHash{$all}[$i]/$attemptedProbHash{$all}[$i]+.5) if $attemptedProbHash{$all}[$i]; $dataRow .= "$item $DELIM"; } $dataRow =~ s|$DELIM$||; ## remove last \$DELIM push @dataArray, $dataRow; $dataRow = "average incorrect $DELIM"; ## all recitations and total # of students for ($i=1;$i<=$noOfProbs;$i++) { $item =0; ## avg # of incorrect attempts of students who have attempted this problem $item = (int(10*$NHash{$all}[$i]/$attemptedProbHash{$all}[$i]+.5))/10 if $attemptedProbHash{$all}[$i]; $item = sprintf '%.1f', $item; $dataRow .= "$item $DELIM"; } $dataRow =~ s|$DELIM$||; ## remove last \$DELIM push @dataArray, $dataRow; print <Data on individual problems by recitation. $all is the total for all included recitations EOF ### output the html table #$string = &delimitedArray2htmlTable(\@dataArray, 'htmltable'); #print "${string}
"; ## display data for recitations foreach $recitationName (@recitationNameArray) { ## add blank row to table to seperate recitations $dataRow = '
'; push @dataArray, $dataRow; # @dataArray =(); $dataRow = "$recitationName $DELIM"; for ($i=1;$i<=$noOfProbs;$i++) { $dataRow .= "\# $i $DELIM"; } $dataRow =~ s|$DELIM$||; ## remove last \$DELIM push @dataArray, $dataRow; $dataRow = "\% attempting $DELIM"; for ($i=1;$i<=$noOfProbs;$i++) { $item =0; ## percent of students who have attempted this problem $item = int(100*$attemptedProbHash{$recitationName}[$i]/$allStudentsHash{$recitationName}+.5) if $allStudentsHash{$recitationName}; $dataRow .= "$item $DELIM"; } $dataRow =~ s|$DELIM$||; ## remove last \$DELIM push @dataArray, $dataRow; $dataRow = "percent correct $DELIM"; ## all recitations and total # of students for ($i=1;$i<=$noOfProbs;$i++) { $item =0; ## % of students who have attempted this problem $item = int(100*$YHash{$recitationName}[$i]/$attemptedProbHash{$recitationName}[$i]+.5) if $attemptedProbHash{$recitationName}[$i]; $dataRow .= "$item $DELIM"; } $dataRow =~ s|$DELIM$||; ## remove last \$DELIM push @dataArray, $dataRow; $dataRow = "average incorrect $DELIM"; ## all recitations and total # of students for ($i=1;$i<=$noOfProbs;$i++) { $item =0; ## avg # of incorrect attempts of students who have attempted this problem $item = (int(10*$NHash{$recitationName}[$i]/$attemptedProbHash{$recitationName}[$i]+.5))/10 if $attemptedProbHash{$recitationName}[$i]; $item = sprintf '%.1f', $item; $dataRow .= "$item $DELIM"; } $dataRow =~ s|$DELIM$||; ## remove last \$DELIM push @dataArray, $dataRow; # ## output the html table # my $string = &delimitedArray2htmlTable(\@dataArray, 'htmltable'); # print "${string}
"; } ## output the html table $string = &delimitedArray2htmlTable(\@dataArray, 'htmltable'); print "${string}
"; ## Now print everything again for excluded recitations ################################################################################################## print <

Current Statistics for Excluded Recitations

Excluded recitations typically contain practices uses, T.A.'s, prof's etc. The list of excluded recitations in contained in the webworkCourse.ph file and typically consists of a recitation with an empty name.

EOF &initializeAndLoadUp(\@excludedRecitationNameArray,'Excluded'); $all = 'Excluded'; ## create $dat arrays with the info. on average scores, etc @dataArray =(); ## first row $dataRow = "recitations$DELIM \# of students$DELIM \% attempting set $setNumber$DELIM average score$DELIM possible score"; push @dataArray, $dataRow; ## display whole course data $dataRow = "$all $DELIM $allStudentsHash{$all} $DELIM"; ## all recitations and total # of students $item =0; ## % of students who have attempted at least one problem in set $item = int(100*$attemptedSetHash{$all}/$allStudentsHash{$all}+.5) if $allStudentsHash{$all}; $dataRow .= "$item $DELIM"; $item =0; ## avg score of students who have attempted at least one problem in set $item = (int($totalScoreHash{$all} *10/$attemptedSetHash{$all}+.5))/10 if $attemptedSetHash{$all}; $item = sprintf '%.1f', $item; $dataRow .= "$item $DELIM"; $dataRow .= "$total_possible"; push @dataArray, $dataRow; ## display data for recitations foreach $recitationName (@excludedRecitationNameArray) { $dataRow = "$recitationName $DELIM $allStudentsHash{$recitationName} $DELIM"; ## all recitations and total # of students $item =0; ## % of students who have attempted at least one problem in set $item = int(100*$attemptedSetHash{$recitationName}/$allStudentsHash{$recitationName}+.5) if $allStudentsHash{$recitationName}; $dataRow .= "$item $DELIM"; $item =0; ## avg score of students who have attempted at least one problem in set $item = (int($totalScoreHash{$recitationName} *10/$attemptedSetHash{$recitationName}+.5))/10 if $attemptedSetHash{$recitationName}; $item = sprintf '%.1f', $item; $dataRow .= "$item $DELIM"; $dataRow .= "$total_possible"; push @dataArray, $dataRow; } # print "

 @dataArray <\pre>";

print <

Overall Scores by recitation. $all is the total for all excluded recitations

EOF ## output the html table $string = &delimitedArray2htmlTable(\@dataArray, 'htmltable'); print "${string}
"; ## now output the info on individaul problems ### display whole course data @dataArray =(); $dataRow = "$all $DELIM"; for ($i=1;$i<=$noOfProbs;$i++) { $dataRow .= "\# $i $DELIM"; } $dataRow =~ s|$DELIM$||; ## remove last \$DELIM push @dataArray, $dataRow; $dataRow = "\% attempting $DELIM"; for ($i=1;$i<=$noOfProbs;$i++) { $item =0; ## percent of students who have attempted this problem $item = int(100*$attemptedProbHash{$all}[$i]/$allStudentsHash{$all}+.5) if $allStudentsHash{$all}; $dataRow .= "$item $DELIM"; } $dataRow =~ s|$DELIM$||; ## remove last \$DELIM push @dataArray, $dataRow; $dataRow = "percent correct $DELIM"; ## all recitations and total # of students for ($i=1;$i<=$noOfProbs;$i++) { $item =0; ## % of students who have attempted this problem $item = int(100*$YHash{$all}[$i]/$attemptedProbHash{$all}[$i]+.5) if $attemptedProbHash{$all}[$i]; $dataRow .= "$item $DELIM"; } $dataRow =~ s|$DELIM$||; ## remove last \$DELIM push @dataArray, $dataRow; $dataRow = "average incorrect $DELIM"; ## all recitations and total # of students for ($i=1;$i<=$noOfProbs;$i++) { $item =0; ## avg # of incorrect attempts of students who have attempted this problem $item = (int(10*$NHash{$all}[$i]/$attemptedProbHash{$all}[$i]+.5))/10 if $attemptedProbHash{$all}[$i]; $item = sprintf '%.1f', $item; $dataRow .= "$item $DELIM"; } $dataRow =~ s|$DELIM$||; ## remove last \$DELIM push @dataArray, $dataRow; print <Data on individual problems by recitation. $all is the total for all excluded recitations EOF ### output the html table #$string = &delimitedArray2htmlTable(\@dataArray, 'htmltable'); #print "${string}
"; ## display data for recitations foreach $recitationName (@excludedRecitationNameArray) { ## add blank row to table to seperate recitations $dataRow = '
'; push @dataArray, $dataRow; # @dataArray =(); $dataRow = "$recitationName $DELIM"; for ($i=1;$i<=$noOfProbs;$i++) { $dataRow .= "\# $i $DELIM"; } $dataRow =~ s|$DELIM$||; ## remove last \$DELIM push @dataArray, $dataRow; $dataRow = "\% attempting $DELIM"; for ($i=1;$i<=$noOfProbs;$i++) { $item =0; ## percent of students who have attempted this problem $item = int(100*$attemptedProbHash{$recitationName}[$i]/$allStudentsHash{$recitationName}+.5) if $allStudentsHash{$recitationName}; $dataRow .= "$item $DELIM"; } $dataRow =~ s|$DELIM$||; ## remove last \$DELIM push @dataArray, $dataRow; $dataRow = "percent correct $DELIM"; ## all recitations and total # of students for ($i=1;$i<=$noOfProbs;$i++) { $item =0; ## % of students who have attempted this problem $item = int(100*$YHash{$recitationName}[$i]/$attemptedProbHash{$recitationName}[$i]+.5) if $attemptedProbHash{$recitationName}[$i]; $dataRow .= "$item $DELIM"; } $dataRow =~ s|$DELIM$||; ## remove last \$DELIM push @dataArray, $dataRow; $dataRow = "average incorrect $DELIM"; ## all recitations and total # of students for ($i=1;$i<=$noOfProbs;$i++) { $item =0; ## avg # of incorrect attempts of students who have attempted this problem $item = (int(10*$NHash{$recitationName}[$i]/$attemptedProbHash{$recitationName}[$i]+.5))/10 if $attemptedProbHash{$recitationName}[$i]; $item = sprintf '%.1f', $item; $dataRow .= "$item $DELIM"; } $dataRow =~ s|$DELIM$||; ## remove last \$DELIM push @dataArray, $dataRow; # ## output the html table # my $string = &delimitedArray2htmlTable(\@dataArray, 'htmltable'); # print "${string}
"; } ## output the html table $string = &delimitedArray2htmlTable(\@dataArray, 'htmltable'); print "${string}
"; #################################################################################################### print &htmlBOTTOM("profCourseRecData.pl", \%inputs, 'profCourseRecDataHelp.html'); # begin Timing code my $endTime = new Benchmark; &Global::logTimingInfo($beginTime,$endTime,"profCourseRecData.pl",$inputs{'course'},$inputs{'user'}); # end Timing code exit; ##subroutines sub processRecitationNameArrays { ## first consider all blank entries (i.e. empty or white space) in excludedRecitationNameArray ## to be the same recitation, namely ' ' my %temp_hash =(); my $recitationName; foreach $recitationName (@excludedRecitationNameArray) { if ((!defined ($recitationName)) or ($recitationName =~ m|^\s*$|)) {$recitationName = ' ';} $temp_hash{$recitationName} =1; } @excludedRecitationNameArray = keys %temp_hash; ## Make sure excludedRecitationNameArray is a subset of recitationNameArray %temp_hash =(); grep($temp_hash{$_}++,@recitationNameArray); @excludedRecitationNameArray = grep($temp_hash{$_},@excludedRecitationNameArray); ## Now remove excluded recitations from recitation list %temp_hash =(); grep($temp_hash{$_}++,@excludedRecitationNameArray); @recitationNameArray = grep(!$temp_hash{$_},@recitationNameArray); @recitationNameArray = sort @recitationNameArray; @excludedRecitationNameArray = sort @excludedRecitationNameArray; } sub initializeAndLoadUp { my ($recitationNameArrayref, $wholeCourseName) = @_; my @recitationNameArray = @$recitationNameArrayref; my $all = $wholeCourseName; my ($recitationName,$i,$score); ## compute total possible points $total_possible = 0; for ($i=1;$i<=$noOfProbs;$i++) {$total_possible += $problemValueList[$i];} foreach $recitationName (@recitationNameArray) { $totalScoreHash{$recitationName} = 0; $attemptedSetHash{$recitationName} = 0; $allStudentsHash{$recitationName} = 0; for ($i=1;$i<=$noOfProbs;$i++) { $NHash{$recitationName}[$i]=0; ## contains number of incorrect responses $YHash{$recitationName}[$i]=0; ## contains totals of problem scores (i.e. a ## number in [0,1] for each problem $attemptedProbHash{$recitationName}[$i]=0; } } ## load up hashes with data my @pinNumbersArray = &getAllProbSetKeysForSet($setNumber); my ($studentAttemptedAProblem, $numIncorr, $pin, $status); foreach $pin (@pinNumbersArray) { &attachProbSetRecord($pin); $status = getStudentStatus($pin); next if dropStatus($status); $studentAttemptedAProblem = 0; $recitationName = &getClassRecitation($pin); if ((!defined ($recitationName)) or ($recitationName =~ m|^\s*$|)){ $recitationName = ' '; } $allStudentsHash{$recitationName} += 1; for ($i=1;$i<=$noOfProbs;$i++) { if (&getProblemAttempted($i,$pin)) { $studentAttemptedAProblem = 1; $numIncorr = &getProblemNumOfIncorrectAns($i,$pin); $numIncorr =0 unless defined $numIncorr; $numIncorr = &min($numIncorr,99); $NHash{$recitationName}[$i] += $numIncorr; $attemptedProbHash{$recitationName}[$i] += 1; $score = &getProblemStatus($i,$pin); $YHash{$recitationName}[$i] += $score; $totalScoreHash{$recitationName} += round_score($score*$problemValueList[$i]); } } if ($studentAttemptedAProblem) {$attemptedSetHash{$recitationName} += 1;} } ## initialize whole course data $totalScoreHash{$all} = 0; $attemptedSetHash{$all} = 0; $allStudentsHash{$all} = 0; for ($i=1;$i<=$noOfProbs;$i++) { $NHash{$all}[$i]=0; $YHash{$all}[$i]=0; $attemptedProbHash{$all}[$i]=0; } ## compute whole course data foreach $recitationName (@recitationNameArray) { $totalScoreHash{$all} += $totalScoreHash{$recitationName}; $attemptedSetHash{$all} += $attemptedSetHash{$recitationName}; $allStudentsHash{$all} += $allStudentsHash{$recitationName}; for ($i=1;$i<=$noOfProbs;$i++) { $NHash{$all}[$i] += $NHash{$recitationName}[$i]; $YHash{$all}[$i] += $YHash{$recitationName}[$i]; $attemptedProbHash{$all}[$i] += $attemptedProbHash{$recitationName}[$i]; } } } ## find unique name sub uniqueCourseName { my $all = $classID; if (exists $allStudentsHash{$all}) { my $j = 1; $all = "${all}$j"; while (exists $allStudentsHash{$all}) { $j++; $all = "${all}$j"; } } $all } sub warningMsgPage { my ($inputref,$warningMsg) = @_; my %inputs = %$inputref; # print HTML text print &htmlTOP("Scoring Utilities"); # print navigation buttons print qq! [Up]

!; print <

WeBWorK scoring WARNING message for $classID:

EOF print "
";
print $warningMsg;
print "
"; print "To Continue displaying data for $setNumber, check the \"Continue\" check box and then select \"Continue displaying data for $setNumber\".
To Quit and return to the Scoring page, select the \"Up\" buttom."; ## profScoring form -- allows you to score problem sets print <
EOF print qq{
Continue }; # resume printing the rest of the form print < EOF print &htmlBOTTOM("profLogin.pl", \%inputs); exit; } #end of warning Page