' );
- return;
- }
- my $shome=&Apache::lonnet::homeserver( $sname,$sdom );
- my $reply=&Apache::lonnet::reply('dump:'.$sdom.':'.$sname.':'.$cid,$shome );
- my %result = ();
- my $ResId;
- my $PrOrd;
- my $Code;
- my $Tries;
- my $TotalTries = 0;
- my $ParCr = 0;
- my $Wrongs;
- my %TempHash;
- my $Version;
- my $LatestVersion;
- my $PtrTry='';
- my $PtrCod='';
- my $SetNo=0;
- my $Str = "\n".'
'.
- "\n".'
'.
- "\n".'
#
'.
- "\n".'
Set Title
'.
- "\n".'
Results
'.
- "\n".'
Tries
'.
- "\n".'
';
- unless ($reply=~/^error\:/) {
- foreach (split(/\&/,$reply)){
- my ($name,$value)=split(/\=/,&Apache::lonnet::unescape($_));
- $result{$name}=$value;
- }
- foreach my $CurCol (@cols) {
- if (!$CurCol){
- my $Set=&Apache::lonnet::declutter($hash{'map_id_'.$1});
- if ( $Set ) {
- $SetNo++;
- $Str .= "\n"."
'."\n");
- $r->rflush();
+
+sub LoadClassFile {
+ my $file="/home/minaeibi/class.txt";
+ open(FILEID, "<$file");
+ my $line;
+ %Grade=();
+ while ($line=) {
+ my ($id,$ex1,$ex2,$ex3,$ex4,$hw,$final,$grade)=split(' ',$line);
+ $Grade{$id}=$grade;
+ }
}
-
-# ------------------------------------------- Prepare Statistics Table
-sub PreStatTable {
- my $CacheDB = "/home/httpd/perl/tmp/$ENV{'user.name'}".
- "_$ENV{'user.domain'}_$cid\_statistics.db";
- my $GraphDB = "/home/httpd/perl/tmp/$ENV{'user.name'}".
- "_$ENV{'user.domain'}_$cid\_graph.db";
- my $CachDisFac = "/home/httpd/perl/tmp/$ENV{'user.name'}".
- "_$ENV{'user.domain'}_$cid\_DiscFactor.db";
- $r->print(' ');
- my $Ptr = '';
- $Ptr .= ' Sorting Type: '."\n".
- ' '."\n";
- $Ptr .= ' ';
- $Ptr .= ''."\n";
- $Ptr .= ' ';
- $Ptr .= ''."\n";
+#------- Classification
+sub Classify {
+ my ($DiscFac, $students)=@_;
+ &LoadClassFile();
+ my $Count=0;
+ my @List=();
+ my @LS=();
+ my @LF=();
+ my @LM=();
+ my $cf=0;
+ my $cs=0;
+ my $cm=0;
+ foreach (keys(%$DiscFac)){
+ my @l=split(/\:/,$_);
+ if (!($students->{$l[1]})) {next;}
+ my $Grade=$Grade{$students->{$l[1]}};
+ if( $Grade > 3 ) {
+ $cs++;
+ push(@LS,("$l[6],$l[5],$l[4],$l[7],$l[8],$l[9],Successful"));
+ } elsif ( $Grade > 2 ) {
+ $cm++;
+ push(@LM,("$l[6],$l[5],$l[4],$l[7],$l[8],$l[9],Average"));
+ } else {
+ $cf++;
+ push(@LF,("$l[6],$l[5],$l[4],$l[7],$l[8],$l[9],Failed"));
+ }
+ }
+ for(my $n=0;$n<$cs;$n++){$r->print(' '.$LS[$n]);}
+ for(my $n=0;$n<$cm;$n++){$r->print(' '.$LM[$n]);}
+ for(my $n=0;$n<$cf;$n++){$r->print(' '.$LF[$n]);}
+}
- $Ptr .= '
'.
- ' #Stdnts: Total Number of Students opened the problem. '.
- ' Tries : Total Number of Tries for solving the problem. '.
- ' Mod : Maximunm Number of Tries for solving the problem. '.
- ' Mean : Average Number of the tries. [ Tries / #Stdnts ] '.
- ' #YES : Number of students solved the problem correctly. '.
- ' #yes : Number of students solved the problem by override. '.
- ' %Wrng : Percentage of students tried to solve the problem but'.
- ' still incorrect. [ 100*((#Stdnts-(#YES+#yes))/#Stdnts) ] '.
-# ' DoDiff : Degree of Difficulty of the problem. [ Tries/(#YES+#yes+0.1) ] '.
- ' DoDiff : Degree of Difficulty of the problem. [ 1 - ((#YES+#yes) / Tries) ] '.
- ' S.D. : Standard Deviation of the tries.'.
- '[ sqrt(sum((Xi - Mean)^2)) / (#Stdnts-1)'.
- ' where Xi denotes every student\'s tries ] '.
- ' Skew. : Skewness of the students tries.'.
- ' [ (sqrt( sum((Xi - Mean)^3) / #Stdnts)) / (S.D.^3) ] '.
-# ' Dis.F. : Discrimination Factor. [ Sum of Partial Credits Awarded / Total Number of Tries in %27 upper and lower students]'.
- '
';
+sub ProcAct {
+ # return;
+ my ($Act,$Submit)=@_;
+ my @Act=split(/\@/,$Act);
+ @Act = sort(@Act);
+
+ ##$r->print(' '.$#Act);
+ ##for(my $n=0;$n<=$#Act;$n++){
+## $r->print(' n='.$n.')'.$Act[$n]);
+## }
+
+# my $Beg=$Act[0];
+ my $Dif=$Submit-$Act[0];
+ $Dif = ($Dif>0) ? ($Dif/3600) : 0;
+
+# $r->print(' Access Number = '.$#Act.' Submit Time='.$Submit.' First Access='.$Act[0].' Last Access='.$Act[$#Act].' Submit - First = '.$Dif.'');
- $r->print($Ptr);
- $r->rflush();
- if ((-e "$CacheDB")&&($ENV{'form.sort'} ne 'Recalculate Statistics')) {
- if (tie(%CachData,'GDBM_File',"$CacheDB",&GDBM_READER,0640)) {
- tie(%GraphDat,'GDBM_File',$GraphDB,&GDBM_WRCREAT,0640);
- &Cache_Statistics();
+#time spent for solving the problem
+# $r->print(' Def'.($Act[$#Act-1]-$Act[0]));
+
+ return $Dif;
+}
+
+
+
+sub LoadActivityLog {
+# my $CacheDB = "/home/minaeibi/act183.log.cache";
+ my $CacheDB = "/home/httpd/perl/tmp/act183.log.cache";
+
+ if (-e "$CacheDB") {
+ if (tie(%Activity,'GDBM_File',"$CacheDB",&GDBM_READER,0640)) {
+ return;
}
else {
- $r->print("Unable to tie hash to db file");
+ $r->print("Unable to tie log Cache hash to db file");
}
}
else {
- if (tie(%CachData,'GDBM_File',$CacheDB,&GDBM_WRCREAT,0640)) {
- tie(%DiscFac,'GDBM_File',$CachDisFac,&GDBM_WRCREAT,0640);
- tie(%GraphDat,'GDBM_File',$GraphDB,&GDBM_WRCREAT,0640);
- foreach (keys %DiscFac) {delete $CachData{$_};}
- foreach (keys %CachData) {delete $CachData{$_};}
- $DiscFlag=0;
- &Build_Statistics();
+ if (tie(%Activity,'GDBM_File',$CacheDB,&GDBM_WRCREAT,0640)) {
+ foreach (keys %Activity) {delete $Activity{$_};}
+ &Build_log();
}
else {
- $r->print("Unable to tie hash to db file");
+ $r->print("Unable to tie log Build hash to db file");
}
}
- #$r->print('Total instances of the problems : '.($p_count*($#students+1)));
+}
+
+sub Build_log {
+ my $file="/home/minaeibi/act183.log";
+ open(FILEID, "<$file");
+ my $line;
+ my $count=0;
+ while ($line=) {
+ my ($time,$machine,$what)=split(':',$line);
+ $what=&Apache::lonnet::unescape($what);
+ my @accesses=split('&',$what);
+
+ foreach my $access (@accesses) {
+
+ $count++;
+
+ my ($date,$resource,$who,$domain,$post,@posts)=split(':',$access);
+ if (!$resource) { next; }
+ my $res=&Apache::lonnet::unescape($resource);
+ if (($res =~ /\.problem/)) {
+ $Activity{$who.':'.$res}.=$date.'@';
+ #$r->print(' '.$time.':'.$who.'---'.$res);
+ &Update_PrgInit($count);
+
+ }
+ }
+ }
+
+# my $c=1;
+# foreach (sort keys %Activity) {
+# $r->print(' '.$c.')'.$_.' ... '.$Activity{$_});
+# $c++;
+# }
- untie(%CachData);
- untie(%GraphDat);
- untie(%DiscFac);
+}
+
+sub Activity {
+# $rid=~/(\d+)\.(\d+)/;
+# my $MapId=$1;
+# my $PrbId=$2;
+# my $MapOrg = $hash{'map_id_'.$MapId};
+# my $Map = &Apache::lonnet::declutter($MapOrg);
+# my $URI = $hash{'src_'.$rid};
+# my $Symb = $Map.'___'.$PrbId.'___'.&Apache::lonnet::declutter($URI);
+ my $file="/home/minaeibi/activity.log";
+ my $userid='adamsde1';
+ $r->print(" Using $file");
+ $r->rflush();
+ open(FILEID, "<$file");
+ my $line;
+ my @allaccess;
+ my $Count=0;
+ while ($line=) {
+ my ($time,$machine,$what)=split(':',$line);
+ $what=&Apache::lonnet::unescape($what);
+ my @accesses=split('&',$what);
+ foreach my $access (@accesses) {
+ my ($date,$resource,$who,$domain,$post,@posts)=split(':',$access);
+ #if ($who ne $userid) { next; }
+ if (!$resource) { next; }
+ my $res=&Apache::lonnet::unescape($resource);
+ if (($res =~ /\.(sequence|problem|htm|html|page)/)) {
+ $Count++;
+ $r->print(" $Count) ".localtime($date).": $who --> $res");
+# if ($post) {
+# $Count++;
+# $r->print(" $Count) Sent data ".join(':',
+# &Apache::lonnet::unescape(@posts)).'');
+# }
+ $r->rflush();
+ }
+ #push (@allaccess,unescape($access));
+ #print $machine;
+ }
+ }
+# @allaccess=sort(@allaccess);
+# $Count=0;
+# foreach my $access (@allaccess) {
+# my ($date,$resource,$who,$domain,$post,@posts)=split(':',$access);
+# $Count++;
+# $r->print(" $Count) $date: $who --> $resource");
+# $r->rflush();
+# if ($post) {
+# $r->print(" Sent data ".join(':',unescape(@posts)).'');
+# }
+# }
}
-# ------------------------------------- Find the section of student in a course
-
-sub usection {
- my ($udom,$unam,$courseid)=@_;
- $courseid=~s/\_/\//g;
- $courseid=~s/^(\w)/\/$1/;
- map {
- my ($key,$value)=split(/\=/,$_);
- $key=&Apache::lonnet::unescape($key);
- if ($key=~/^$courseid(?:\/)*(\w+)*\_st$/) {
- my $section=$1;
- if ($key eq $courseid.'_st') { $section=''; }
- my ($dummy,$end,$start)=split(/\_/,&Apache::lonnet::unescape($value));
- $section=($section) ? $section : '(none)';
-# $section=(int($section)) ? int($section) : $section;
-# $r->print($unam.'...'.$section.' ');
- return $section;
- }
- } split(/\&/,&Apache::lonnet::reply('dump:'.$udom.':'.$unam.':roles',
- &Apache::lonnet::homeserver($unam,$udom)));
- return '';
+sub InitAnalysis {
+ my ($uri,$part,$problem,$student,$courseID)=@_;
+ my ($uname,$udom)=split(/\:/,$student);
+
+
+ # Render the student's view of the problem. $Answ is the problem
+ # Stringafied
+ my $Answ=&Apache::lonnet::ssi($uri,('grade_target' => 'analyze',
+ 'grade_username' => $uname,
+ 'grade_domain' => $udom,
+ 'grade_courseid' => $courseID,
+ 'grade_symb' => $problem));
+# my $Answ=&Apache::lonnet::ssi($URI,('grade_target' => 'analyze'));
+
+# (my $garbage,$Answ)=split(/_HASH_REF__/,$Answ,2);
+ %Answer=();
+ %Answer=&Apache::lonnet::str2hash($Answ);
+
+ my $parts='';
+ foreach my $elm (@{$Answer{"parts"}}) {
+ $parts.="$elm,";
+ }
+ chop($parts);
+ my $conc='';
+ foreach my $elm (@{$Answer{"$parts.concepts"}}) {
+ $conc.="$elm@";
+ }
+ chop($conc);
+
+ @Concepts=split(/\@/,$conc);
+ foreach my $concept (@{$Answer{"$parts.concepts"}}) {
+ foreach my $foil (@{$Answer{"$parts.concept.$concept"}}) {
+ $foil_to_concept{$foil} = $concept;
+ #$ConceptData{$foil} = $Answer{"$parts.foil.value.$foil"};
+ }
+ }
+
+ return;
}
-# ------ Dump the Student's DB file and handling the data for statistics table
+sub Interval {
+ my ($part,$symb)=@_;
+ my $Int=$ConceptData{"Interval"};
+ my $due = &Apache::lonnet::EXT('resource.$part.duedate',$symb)+1;
+ my $opn = &Apache::lonnet::EXT('resource.$part.opendate',$symb);
+ my $add=int(($due-$opn)/$Int);
+ $ConceptData{"Int.0"}=$opn;
+ for (my $i=1;$i<$Int;$i++) {
+ $ConceptData{"Int.$i"}=$opn+$i*$add;
+ }
+ $ConceptData{"Int.$Int"}=$due;
+ for (my $i=0;$i<$Int;$i++) {
+ for (my $n=0; $n<=$#Concepts; $n++ ) {
+ my $tmp=$Concepts[$n];
+ $ConceptData{"$tmp.$i.true"}=0;
+ $ConceptData{"$tmp.$i.false"}=0;
+ }
+ }
+}
+
+
+sub ShowOpGraph {
+ my ($cache, $students, $courseID)=@_;
+ my $uri = $cache->{'AnalyzeURI'};
+ my $part = $cache->{'AnalyzePart'};
+ my $problem = $cache->{'AnalyzeProblem'};
+ my $title = $cache->{'AnalyzeTitle'};
+ my $interval = $cache->{'Interval'};
+ $ConceptData{"Interval"} = $interval;
+
+ #Initialize the option response true answers
+ &InitAnalysis($uri, $part, $problem, $students->[0],$courseID);
+
+ #compute the intervals
+ &Interval($part,$problem);
+
+ $title =~ s/\ /"_"/eg;
+ $r->print(' '.$uri.'');
+ $r->rflush();
+
+ #Java script Progress window
+ &Create_PrgWin();
+ &Update_PrgWin("Starting-to-analyze-problem");
+ for (my $index=0;$index<(scalar @$students);$index++) {
+ &Update_PrgWin($index);
+ &OpStatus($problem,$students->[$index],$courseID);
+ }
+ &Close_PrgWin();
+
+ $r->print(' ');
+ for (my $k=0; $k<$interval; $k++ ) {
+ &DrawGraph($k,$title);
+ }
+ for (my $k=0; $k<$interval; $k++ ) {
+ &DrawTable($k);
+ }
+#$Apache::lonxml::debug=1;
+#&Apache::lonhomework::showhash(%ConceptData);
+#$Apache::lonxml::debug=0;
+ my $Answ=&Apache::lonnet::ssi($uri);
+ $r->print(" Here you can see the Problem: $Answ");
+}
+
+sub DrawTable {
+ my $k=shift;
+ my $Max=0;
+ my @data1;
+ my @data2;
+ my $Correct=0;
+ my $Wrong=0;
+ for (my $n=0; $n<=$#Concepts; $n++ ) {
+ my $tmp=$Concepts[$n];
+ $data1[$n]=$ConceptData{"$tmp.$k.true"};
+ $Correct+=$data1[$n];
+ $data2[$n]=$ConceptData{"$tmp.$k.false"};
+ $Wrong+=$data2[$n];
+ my $Sum=$data1[$n]+$data2[$n];
+ if ( $Max<$Sum ) {$Max=$Sum;}
+ }
+ for (my $n=0; $n<=$#Concepts; $n++ ) {
+ if ($data1[$n]+$data2[$n]<$Max) {
+ $data2[$n]+=$Max-($data1[$n]+$data2[$n]);
+ }
+ }
+ my $P_No = $#data1+1;
+# $r->print(' From: ['.localtime($ConceptData{'Int.'.($k-1)}).
+# '] To: ['.localtime($ConceptData{"Int.$k"}).']');
+ my $Str = "\n".'
Total Number of Students opened the problem.';
+ $Ptr .= '
';
+ $Ptr .= 'Tries:
';
+ $Ptr .= '
Total Number of Tries for solving the problem.';
+ $Ptr .= '
';
+ $Ptr .= 'Mod:
';
+ $Ptr .= '
Maximunm Number of Tries for solving the problem.';
+ $Ptr .= '
';
+ $Ptr .= 'Mean:
';
+ $Ptr .= '
Average Number of the tries. [ Tries / #Stdnts ]';
+ $Ptr .= '
';
+ $Ptr .= '#YES:
';
+ $Ptr .= '
Number of students solved the problem correctly.';
+ $Ptr .= '
';
+ $Ptr .= '#yes:
';
+ $Ptr .= '
Number of students solved the problem by override.';
+ $Ptr .= '
';
+ $Ptr .= '%Wrng:
';
+ $Ptr .= '
Percentage of students tried to solve the problem ';
+ $Ptr .= 'but still incorrect. [ 100*((#Stdnts-(#YES+#yes))/#Stdnts) ]';
+ $Ptr .= '
';
+# Kashy formula
+# ' DoDiff : Degree of Difficulty of the problem. '.
+# '[ Tries/(#YES+#yes+0.1) ] '.
+ #Gerd formula
+ $Ptr .= 'DoDiff:
';
+ $Ptr .= '
Degree of Difficulty of the problem. ';
+ $Ptr .= '[ 1 - ((#YES+#yes) / Tries) ]';
+ $Ptr .= '
';
+ $Ptr .= 'S.D.:
';
+ $Ptr .= '
Standard Deviation of the tries. ';
+ $Ptr .= '[ sqrt(sum((Xi - Mean)^2)) / (#Stdnts-1) ';
+ $Ptr .= 'where Xi denotes every student\'s tries ]';
+ $Ptr .= '
';
+ $Ptr .= 'Skew.:
';
+ $Ptr .= '
Skewness of the students tries.';
+ $Ptr .= '[(sqrt( sum((Xi - Mean)^3) / #Stdnts)) / (S.D.^3)]';
+ $Ptr .= '
';
+ $Ptr .= 'Dis.F.:
';
+ $Ptr .= '
Discrimination Factor: A Standard for evaluating the ';
+ $Ptr .= 'problem according to a Criterion ';
+ $Ptr .= '[Applied Criterion in %27 Upper Students - ';
+ $Ptr .= 'Applied the same Criterion in %27 Lower Students] ';
+ $Ptr .= '1st Criterion for Sorting the Students: ';
+ $Ptr .= 'Sum of Partial Credit Awarded / Total Number of Tries ';
+ $Ptr .= '2nd Criterion for Sorting the Students: ';
+ $Ptr .= 'Total number of Correct Answers / Total Number of Tries';
+ $Ptr .= '
';
+ $Ptr .= '
Disc.
';
+ $Ptr .= '
Number of Students had at least one discussion.';
+ $Ptr .= '
';
+
+ return $Ptr;
+}
+
+#---- END Problem Statistics Web Page ----------------------------------------
+
+#---- Problem Statistics Graph Web Page --------------------------------------
+
# ------------------------------------------- Prepare data for Graphical chart
sub GetGraphData {
- my $Tag = shift;
+ my $ylab = shift;
my $Col;
my $data='';
my $count = 0;
@@ -800,12 +1266,12 @@ sub GetGraphData {
foreach (keys %GraphDat) {delete $GraphDat{$_};}
if (-e "$GraphDB") {
if (tie(%GraphDat,'GDBM_File',"$GraphDB",&GDBM_READER,0640)) {
- if ( $Tag eq 'DoDiff Graph' ) {
- $Tag = 'Degree-of-Difficulty';
+ if ( $ylab eq 'DoDiff Graph' ) {
+ $ylab = 'Degree-of-Difficulty';
$Col = 0;
}
else {
- $Tag = 'Wrong-Percentage';
+ $ylab = 'Wrong-Percentage';
$Col = 1;
}
foreach (sort NumericSort keys %GraphDat) {
@@ -815,314 +1281,877 @@ sub GetGraphData {
$data .= $inf.',';
$count++;
}
+ if ( $Max > 1 ) {
+ $Max += (10 - $Max % 10);
+ $Max = int($Max);
+ }
+ else { $Max = 1; }
untie(%GraphDat);
my $Course = $ENV{'course.'.$cid.'.description'};
$Course =~ s/\ /"_"/eg;
- $GData=$Course.'&'.$Tag.'&'.$Max.'&'.$count.'&'.$data;
-
+ $GData=$Course.'&'.'Problems'.'&'.$ylab.'&'.$Max.'&'.$count.'&'.$data;
}
else {
$r->print("Unable to tie hash to db file");
}
}
}
+#---- Problem Analysis Web Page ----------------------------------------------
+sub IntervalOptions {
+ my ($cache)=@_;
-sub initial {
-# --------------------------------- Initialize the global varaibles
- undef @students;
- undef @cols;
- undef %maps;
- undef %section;
- undef %StuBox;
- undef @list;
- undef %CachData;
- undef %GraphDat;
- undef %DiscFac;
- undef $CurMap;
- undef $CurSec;
- undef $CurStu;
- undef $p_count;
- undef $Pos;
- undef $GData;
- $DiscFlag=0;
- $P_Order=100000;
- $HWN=$P_Order;
+ my $interval = 1;
+ for(my $n=1; $n<=7; $n++) {
+ if($cache->{'Interval'} == $n) {
+ $interval = $n;
+ }
+ }
+
+ my $Ptr = ' Select number of intervals'."\n".
+ ''."\n";
+
+ return $Ptr;
}
+sub OptionResponseTable {
+ my ($cache)=@_;
+ my $Str = '';
+ $Str .= ' Option Response Problems in this course:'."\n";
+ $Str .= '
'."\n";
+ $Str .= "
\#
Problem Title
";
+ $Str .= '
Resource
Analysis
'."\n";
+
+ my $number=1;
+ foreach (split(':::',$cache->{'OptionResponses'})) {
+ my ($uri,$title,$part,$problem)=split('::',$_);
+ my $Temp = ''.$title.'';
+ $Str .= '
';
+ $Str .= '
'.$number.'
';
+ $Str .= '
'.$Temp.'
';
+ $Str .= '
'.$uri.'
';
+ $Str .= '
'."\n";
+ $number++;
+ }
+ $Str .= '
'."\n";
-sub ClassList {
-
- &GetStatus();
-
- $cid=$ENV{'request.course.id'};
- my $chome=$ENV{'course.'.$cid.'.home'};
- my ($cdom,$cnum)=split(/\_/,$cid);
-# ----------------------- Get first and last resource, see if there is anything
- $firstres=$hash{'map_start_/res/'.$ENV{'request.course.uri'}};
- $lastres=$hash{'map_finish_/res/'.$ENV{'request.course.uri'}};
- if (($firstres) && ($lastres)) {
-# ----------------------------------------------------------------- Render page
- my $classlst=&Apache::lonnet::reply
- ('dump:'.$cdom.':'.$cnum.':classlist',$chome);
- my $StudNo = 0;
- unless ($classlst=~/^error\:/) {
- foreach (sort split(/\&/,$classlst)) {
- my ($name,$value)=split(/\=/,$_);
- my ($end,$start)=split(/\:/,&Apache::lonnet::unescape($value));
- $name=&Apache::lonnet::unescape($name);
- my ($sname,$sdom)=split(/\:/,$name);
- my $ssec=&Apache::lonnet::usection($sdom,$sname,$cid);
- if ($ssec==-1) {next;}
- $ssec=($ssec) ? $ssec : '(none)';
- #$ssec=(int($ssec)) ? int($ssec) : $ssec;
- #$r->print($sname.'...'.$ssec.' ');
- $section{$ssec}=$ssec;
- if ($CurSec eq 'All Sections' || $ssec eq $CurSec) {
- $students[$StudNo]=$name;
- $StuBox{$sname}=$ssec;
- }
- $StudNo++;
- }
- }
- else {
- $r->print('
Could not access course data
');
- }
- $r->print("Total number of students : ".($#students+1));
- $r->rflush();
-# --------------- Find all assessments and put them into some linear-like order
- &tracetable($firstres,'&'.$lastres.'&');
-
-# my $c=0;
-# foreach (sort keys %mapsort) {
-# $r->print(' '.$c.')'.$_.' ... '.$mapsort{$_});
-# $c++;
-# }
-#foreach(@cols) {
-# $c++;
-# $r->print(' '.$cols[$c]);
-#}
-#$r->print(' Count = '.$c);
+ return $Str;
+}
+
+#---- END Problem Analysis Web Page ------------------------------------------
+
+#---- Student Assessment Web Page --------------------------------------------
+
+# ------ Create different Student Report
+sub StudentReport {
+ my ($cache, $name)=@_;
+
+ my $Str = '';
+ if($cache->{$name.':error'} =~ /course/) {
+ my ($username)=split(':',$name);
+ $Str .= 'No course data for student ';
+ $Str .= ''.$username.'. ';
+ return $Str;
+ }
+
+ $Str .= "
\#
Set Title
";
+ $Str .= '
Results
Tries
'."\n";
+
+ my $codes;
+ my $attempts;
+ foreach my $sequence (split(':', $cache->{'orderedSequences'})) {
+ if($cache->{'StudentAssessmentMap'} ne 'All Maps' &&
+ $cache->{'StudentAssessmentMap'} ne $cache->{$sequence.':title'}) {
+ next;
+ }
+ $Str .= '
'.$sequence.'
';
+ $Str .= '
'.$cache->{$sequence.':title'}.'
';
+
+ $codes = '';
+ $attempts = '';
+ foreach my $problemID (split(':', $cache->{$sequence.':problems'})) {
+ my $problem = $cache->{$problemID.':problem'};
+ my $LatestVersion = $cache->{$name.':version:'.$problem};
+
+ # Output dashes for all the parts of this problem if there
+ # is no version information about the current problem.
+ if(!$LatestVersion) {
+ foreach my $part (split(/\:/,$cache->{$sequence.':'.
+ $problemID.
+ ':parts'})) {
+ $codes .= "-,";
+ $attempts .= "0,";
+ }
+ next;
+ }
+
+ my %partData=undef;
+ # Initialize part data, display skips correctly
+ # Skip refers to when a student made no submissions on that
+ # part/problem.
+ foreach my $part (split(/\:/,$cache->{$sequence.':'.
+ $problemID.
+ ':parts'})) {
+ $partData{$part.':tries'}=0;
+ $partData{$part.':code'}='-';
+ }
+
+ # Looping through all the versions of each part, starting with the
+ # oldest version. Basically, it gets the most recent
+ # set of grade data for each part.
+ for(my $Version=1; $Version<=$LatestVersion; $Version++) {
+ foreach my $part (split(/\:/,$cache->{$sequence.':'.
+ $problemID.
+ ':parts'})) {
+
+ if(!defined($cache->{$name.":$Version:$problem".
+ ":resource.$part.solved"})) {
+ # No grade for this submission, so skip
+ next;
+ }
+
+ my $tries=0;
+ my $code='U';
+
+ $tries = $cache->{$name.":$Version:$problem".
+ ":resource.$part.tries"};
+ $partData{$part.':tries'}=($tries) ? $tries : 0;
+
+ my $val = $cache->{$name.":$Version:$problem".
+ ":resource.$part.solved"};
+ if ($val eq 'correct_by_student') {$code = 'Y';}
+ elsif ($val eq 'correct_by_override') {$code = 'y';}
+ elsif ($val eq 'incorrect_attempted') {$code = 'N';}
+ elsif ($val eq 'incorrect_by_override'){$code = 'N';}
+ elsif ($val eq 'excused') {$code = 'x';}
+ $partData{$part.':code'}=$code;
+ }
+ }
+
+ # Loop through all the parts for the current problem in the
+ # correct order and prepare the output
+ foreach (split(/\:/,$cache->{$sequence.':'.$problemID.
+ ':parts'})) {
+ $codes .= $partData{$_.':code'}.',';
+ $attempts .= $partData{$_.':tries'}.',';
+ }
+ }
+ $codes =~ s/,$//;
+ $attempts =~ s/,$//;
+ $Str .= '