--- loncom/interface/lonstatistics.pm 2002/05/19 15:44:40 1.20
+++ loncom/interface/lonstatistics.pm 2002/07/17 12:53:00 1.27
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# (Publication Handler
#
-# $Id: lonstatistics.pm,v 1.20 2002/05/19 15:44:40 minaeibi Exp $
+# $Id: lonstatistics.pm,v 1.27 2002/07/17 12:53:00 stredwic Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -31,7 +31,7 @@
# 11/1,11/4,11/16,12/14,12/16,12/18,12/20,12/31 Behrouz Minaei
# YEAR=2002
# 1/22,2/1,2/6,2/25,3/2,3/6,3/17,3/21,3/22,3/26,4/7,5/6 Behrouz Minaei
-# 5/12,5/14,5/15,5/19 Behrouz Minaei
+# 5/12,5/14,5/15,5/19,5/26 Behrouz Minaei
#
###
@@ -42,6 +42,7 @@ use Apache::Constants qw(:common :http);
use Apache::lonnet();
use Apache::lonhomework;
use Apache::loncommon;
+use Apache::loncoursedata;
use HTML::TokeParser;
use GDBM_File;
@@ -49,61 +50,84 @@ use GDBM_File;
my %hash;
my %CachData;
my %GraphDat;
-my %OpResp;
-my %maps;
my %mapsort;
-my %section;
-my %StuBox;
-my %DiscFac;
-my %DisUp;
-my %DisLow;
-my $UpCnt;
-my $CurMap;
-my $CurSec;
-my $CurStu;
-my @cols;
-my @list;
-my @students;
-my $p_count;
my $Pos;
my $r;
-my $OpSel1;
-my $OpSel2;
-my $OpSel3;
-my $OpSel4;
my $GData;
-my $cid;
-my $firstres;
-my $lastres;
-my $DiscFlag;
-my $HWN;
-my $P_Order;
+my %color;
my %foil_to_concept;
my @Concepts;
my %ConceptData;
-my %Header = (0,"Homework Sets Order",1,"#Stdnts",2,"Tries",3,"Mod",
- 4,"Mean",5,"#YES",6,"#yes",7,"%Wrng",8,"DoDiff",
- 9,"S.D.",10,"Skew.",11,"D.F.1st",12,"D.F.2nd");
my %Answer = ();
+sub Activity {
+ 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 =~ /\.(problem|htm|html)/)) {
+ $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)).'');
+# }
+# }
+}
+
+#---- Analyze Web Page ---------------------------------------------------
+
sub InitAnalysis {
- my ($rid, $student)=@_;
- my ($uname,$udom)=split(/\:/,$student);
- $rid=~/(\d+)\.(\d+)/;
- my $symb=&Apache::lonnet::declutter($hash{'map_id_'.$1}).'___'.$2.'___'.
- &Apache::lonnet::declutter($hash{'src_'.$rid});
- my $URI = $hash{'src_'.$rid};
- my $Answ=&Apache::lonnet::ssi($URI,('grade_target' => 'analyze',
- 'grade_username' => $uname,
- 'grade_domain' => $udom,
- 'grade_courseid' => $cid,
- 'grade_symb' => $symb));
-# my $Answ=&Apache::lonnet::ssi($URI,('grade_target' => 'analyze'));
+ my ($uri,$part,$problem,$student,$courseID)=@_;
+ my ($username,$userdomain)=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' => $username,
+ 'grade_domain' => $userdomain,
+ 'grade_courseid' => $courseID,
+ 'grade_symb' => $problem));
+# my $Answ=&Apache::lonnet::ssi($uri,('grade_target' => 'analyze'));
- (my $garbage,$Answ)=split(/_HASH_REF__/,$Answ,2);
+# (undef,$Answ)=split(/_HASH_REF__/,$Answ,2);
%Answer=();
%Answer=&Apache::lonnet::str2hash($Answ);
+# foreach (sort(keys(%Answer))) {
+# $r->print($_.' '.$Answer{$_}.' ');
+# }
+
my $parts='';
foreach my $elm (@{$Answer{"parts"}}) {
$parts.="$elm,";
@@ -122,69 +146,72 @@ sub InitAnalysis {
#$ConceptData{$foil} = $Answer{"$parts.foil.value.$foil"};
}
}
- return $symb;
-}
+ return;
+}
sub Interval {
- my ($rid,$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;
+ my ($part,$symb)=@_;
+ my $interval=$ConceptData{"Interval"};
+ my $due = &Apache::lonnet::EXT('resource.'.$part.'.duedate',$symb)+1;
+ my $open = &Apache::lonnet::EXT('resource.'.$part.'.opendate',$symb);
+ my $add=int(($due-$open)/$interval);
+ $ConceptData{'Interval.0'}=$open;
+ for (my $i=1;$i<$interval;$i++) {
+ $ConceptData{'Interval.'.$i}=$open+$i*$add;
}
- $ConceptData{"Int.$Int"}=$due;
- for (my $i=0;$i<$Int;$i++) {
+ $ConceptData{'Interval.'.$interval}=$due;
+ for (my $i=0;$i<$interval;$i++) {
for (my $n=0; $n<=$#Concepts; $n++ ) {
my $tmp=$Concepts[$n];
- $ConceptData{"$tmp.$i.true"}=0;
- $ConceptData{"$tmp.$i.false"}=0;
+ $ConceptData{$tmp.'.'.$i.'.true'}=0;
+ $ConceptData{$tmp.'.'.$i.'.false'}=0;
}
}
}
-
sub ShowOpGraph {
- my ($InpStr, $Int_No)=@_;
- my ($rid,$part)=split(/\:/,substr($InpStr,8));
- $ConceptData{"Interval"}=$Int_No;
+ my ($cache, $students, $courseID)=@_;
+ my $uri = $cache->{'AnalyzeURI'};
+ my $part = $cache->{'AnalyzePart'};
+ my $problem = $cache->{'AnalyzeProblem'};
+ my $title = $cache->{'AnalyzeProblem'};
+ my $interval = $cache->{'Interval'};
+ $ConceptData{"Interval"} = $interval;
+
#Initialize the option response true answers
- my $symb=&InitAnalysis($rid,$students[0]);
+ &InitAnalysis($uri, $part, $problem, $students->[0],$courseID);
+
#compute the intervals
- &Interval($rid,$part,$symb);
- my $URI = $hash{'src_'.$rid};
- my $Src = $hash{'title_'.$rid};
- $Src =~ s/\ /"_"/eg;
- $r->print(' '.$URI.'');
+ &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<=$#students;$index++) {
- &Update_PrgWin($index);
- &OpStatus($rid,$students[$index]);
+ &Update_PrgWin("Starting to analyze problem",0,0,'');
+ for(my $index=0; $index<(scalar @$students); $index++) {
+ &Update_PrgWin(scalar @$students, $index+1, $students->[$index]);
+ &OpStatus($problem, $students->[$index], $courseID);
}
&Close_PrgWin();
$r->print(' ');
- for (my $k=0; $k<$Int_No; $k++ ) {
- &DrawGraph($k,$Src);
+ for(my $k=0; $k<$interval; $k++ ) {
+ &DrawGraph($k,$title);
}
- for (my $k=0; $k<$Int_No; $k++ ) {
+ 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);
+ my $Answ=&Apache::lonnet::ssi($uri);
$r->print(" Here you can see the Problem: $Answ");
}
-
sub DrawTable {
my $k=shift;
my $Max=0;
@@ -220,9 +247,9 @@ sub DrawTable {
for (my $n=0; $n<=$#Concepts; $n++ ) {
$Str .= "\n"."
".
"\n"."
".($n+1)."
".
- "\n"."
".$Concepts[$n]."
".
- "\n"."
".$data1[$n]."
".
- "\n"."
".$data2[$n]."
".
+ "\n".'
'.$Concepts[$n]."
".
+ "\n".'
'.$data1[$n]."
".
+ "\n".'
'.$data2[$n]."
".
"\n"."
";
}
$Str.='
From:['.localtime($ConceptData{'Int.'.$k}).
@@ -239,86 +266,43 @@ sub DrawTable {
sub DrawGraph {
- my ($k,$Src)=@_;
+ my ($currentInterval,$title)=@_;
my $Max=0;
my @data1;
my @data2;
# Adjust Data and find the Max
- for (my $n=0; $n<=$#Concepts; $n++ ) {
+ for(my $n=0; $n<=$#Concepts; $n++ ) {
my $tmp=$Concepts[$n];
- $data1[$n]=$ConceptData{"$tmp.$k.true"};
- $data2[$n]=$ConceptData{"$tmp.$k.false"};
+ $data1[$n]=$ConceptData{$tmp.'.'.$currentInterval.'.true'};
+ $data2[$n]=$ConceptData{$tmp.'.'.$currentInterval.'.false'};
my $Sum=$data1[$n]+$data2[$n];
- if ( $Max<$Sum ) {$Max=$Sum;}
+ if($Max < $Sum) { $Max = $Sum; }
}
- for (my $n=0; $n<=$#Concepts; $n++ ) {
- if ($data1[$n]+$data2[$n]<$Max) {
+ 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;
+ my $P_No = scalar @data1;
- if ( $Max > 1 ) {
+ if($Max > 1) {
$Max += (10 - $Max % 10);
$Max = int($Max);
- } else { $Max = 1; }
+ } else {
+ $Max = 1;
+ }
-
- my $Titr=($ConceptData{'Interval'}>1) ? $Src.'_interval_'.($k+1) : $Src;
+ my $Titr=($ConceptData{'Interval'}>1) ?
+ $title.'_interval_'.($currentInterval+1) : $title;
# $GData=$Titr.'&Concepts'.'&'.'Answers'.'&'.$Max.'&'.$P_No.'&'.$data1.'&'.$data2;
- $GData="$Titr&Concepts&Answers&$Max&$P_No&".
- (join(',',@data1)).'&'.(join(',',@data2));
+ $GData = $Titr.'&Concepts&Answers&'.$Max.'&'.$P_No.'&';
+ $GData .= (join(',',@data1)).'&'.(join(',',@data2));
$r->print('');
}
-sub AnalyzeProblem {
- # selecting the number of intervals
- my $OpSel='';
- my $CurInt = $ENV{'form.interval'};
- if ($CurInt eq '') {$CurMap = '1';}
- my $Ptr = 'Select number of intervals'."\n".
- ''."\n";
- $r->print( $Ptr );
-
- #the table of option response problems
- $r->print(' Option Response Problems in this course:
');
- my $Str = "\n".'
'.
- "\n".'
'.
- "\n".'
#
'.
- "\n".'
Problem Title
'.
- "\n".'
Resouse
'.
- "\n".'
Address
'.
- "\n".'
';
-
- my $P_No=1;
- foreach (sort keys %OpResp) {
- my ($rid,$part)=split(/\:/,$OpResp{$_});
- my $Temp = ''.$hash{'title_'.$rid}.'';
- $Str .= "\n"."
".
- "\n"."
$P_No
".
- "\n"."
".$Temp."
".
- "\n"."
".$hash{'src_'.$rid}."
".
- "\n"."
".''.'
'.
- "\n"."
";
- $P_No++;
- }
- $Str .= "\n".'
';
- $Str .= "\n".'';
- $r->print($Str);
- $r->rflush();
-}
-
-
sub Decide {
#deciding the true or false answer belongs to each interval
my ($type,$foil,$time)=@_;
@@ -331,13 +315,11 @@ sub Decide {
#restore the student submissions and finding the result
sub OpStatus {
- my ($rid,$student)=@_;
- my ($uname,$udom)=split(/\:/,$student);
+ my ($problem, $student, $courseID)=@_;
+ my ($username,$userdomain)=split(/':'/,$student);
my $code='U';
- $rid=~/(\d+)\.(\d+)/;
- my $symb=&Apache::lonnet::declutter($hash{'map_id_'.$1}).'___'.$2.'___'.
- &Apache::lonnet::declutter($hash{'src_'.$rid});
- my %reshash=&Apache::lonnet::restore($symb,$cid,$udom,$uname);
+ my %reshash=&Apache::lonnet::restore($problem, $courseID, $userdomain,
+ $username);
my @True = ();
my @False = ();
my $flag=0;
@@ -374,600 +356,245 @@ sub OpStatus {
}
}
+#---- END Analyze Web Page ----------------------------------------------
+
+#---- Problem Statistics Web Page ---------------------------------------
#------- Processing upperlist and lowerlist according to each problem
-sub ProcessDisc {
- my @List = @_;
- @List = sort (@List);
- my $Count = $#List+1;
- my $Prb;
+sub ProcessDiscriminant {
+ my ($List) = @_;
+ my @sortedList = sort (@$List);
+ my $Count = scalar @sortedList;
+ my $Problem;
my @Dis;
my $Slvd=0;
my $tmp;
my $Sum1=0;
my $Sum2=0;
- my $nIdx=0;
- my $nStud=0;
- my %Proc;
- undef %Proc;
- while ($nIdx<$Count) {
- ($Prb,$tmp)=split(/\=/,$List[$nIdx]);
+ my $nIndex=0;
+ my $nStudent=0;
+ my %Proc=undef;
+ while ($nIndex<$Count) {
+ ($Problem,$tmp)=split(/\=/,$sortedList[$nIndex]);
@Dis=split(/\+/,$tmp);
- my $Temp = $Prb;
+ my $Temp = $Problem;
do {
- $nIdx++;
- $nStud++;
+ $nIndex++;
+ $nStudent++;
$Sum1 += $Dis[0];
$Sum2 += $Dis[1];
- ($Prb,$tmp)=split(/\=/,$List[$nIdx]);
+ ($Problem,$tmp)=split(/\=/,$sortedList[$nIndex]);
@Dis=split(/\+/,$tmp);
- } while ( $Prb eq $Temp && $nIdx < $Count );
-# $Proc{$Temp}=($Sum1/$nStud).':'.$nStud;
- $Proc{$Temp}=($Sum1/$nStud).':'.($Sum2/$nStud);
-# $r->print("$nIdx) $Temp --> ($nStud) $Proc{$Temp} ");
+ } while ( $Problem eq $Temp && $nIndex < $Count );
+# $Proc{$Temp}=($Sum1/$nStudent).':'.$nStudent;
+ $Proc{$Temp}=($Sum1/$nStudent).':'.($Sum2/$nStudent);
+# $r->print("$nIndex) $Temp --> ($nStudent) $Proc{$Temp} ");
$Sum1=0;
$Sum2=0;
- $nStud=0;
+ $nStudent=0;
}
+
return %Proc;
}
#------- Creating Discimination factor
sub Discriminant {
- my $Count=0;
- foreach (keys(%DiscFac)){
- $Count++;
- }
- $UpCnt = int(0.27*$Count);
+ my ($discriminantFactor)=@_;
+ my @discriminantKeys=keys(%$discriminantFactor);
+ my $Count = scalar @discriminantKeys;
+
+ my $UpCnt = int(0.27*$Count);
my $low=0;
my $up=$Count-$UpCnt;
my @UpList=();
my @LowList=();
+
$Count=0;
- foreach my $key (sort(keys(%DiscFac))){
+ foreach my $key (sort(@discriminantKeys)) {
$Count++;
- #$r->print(" $Count) $key = $DiscFac{$key}");
- if ($low < $UpCnt || $Count > $up) {
- $low++;
- my $str=$DiscFac{$key};
- foreach(split(/\:/,$str)){
- if ($_) {
- if ($low<$UpCnt){push(@LowList,$_);}
- else {push(@UpList,$_);}
- }
- }
- }
+ if($low < $UpCnt || $Count > $up) {
+ $low++;
+ my $str=$discriminantFactor->{$key};
+ foreach(split(/\:/,$str)){
+ if($_) {
+ if($low<$UpCnt) { push(@LowList,$_); }
+ else { push(@UpList,$_); }
+ }
+ }
+ }
}
- %DisUp=&ProcessDisc(@UpList);
- %DisLow=&ProcessDisc(@LowList);
+ my %DisUp = &ProcessDiscriminant(\@UpList);
+ my %DisLow = &ProcessDiscriminant(\@LowList);
+
+ return (\%DisUp, \%DisLow);
}
-
sub NumericSort {
$a <=> $b;
}
-# ------ Create different Student Report
-sub StudentReport {
- my ($sname,$sdom)=@_;
- if ( $sname eq 'All Students' ) {
- $r->print( '
WARNING:
- Please select a student
' );
+sub CreateProblemStatisticsTableHeading {
+ my ($displayFormat,$sequenceSource,$sequenceTitle,$headings)=@_;
+ if($displayFormat eq 'Display CSV Format') {
+ $r->print(' "'.$sequenceTitle.'","');
+ $r->print($sequenceSource.'"');
return;
}
- my %result = &Apache::lonnet::dump($cid,$sdom,$sname);
- 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".'
';
- my ($temp)=keys(%result);
- unless ($temp=~/^error\:/) {
- foreach my $CurCol (@cols) {
- if (!$CurCol){
- my $Set=&Apache::lonnet::declutter($hash{'map_id_'.$1});
- if ( $Set ) {
- $SetNo++;
- $Str .= "\n"."
'.
- ' #Stdnts: Total Number of Students opened the problem. '.
- ' Tries : Total Number of Tries for solving the problem. '.
- ' Max : Maximunm Number of Tries for solving the problem. '.
- ' Avg. : 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) ] '. Kashy formula
- ' DoDiff : Degree of Difficulty of the problem. [ 1 - ((#YES+#yes) / Tries) ] '. #Gerd formula
- ' S.D. : Standard Deviation of the tries.'.
- '[ sqrt(sum((Xi - Avg.)^2)) / (#Stdnts-1)'.
- ' where Xi denotes every student\'s tries ] '.
- ' Skew. : Skewness of the students tries.'.
- ' [ (sqrt( sum((Xi - Avg.)^3) / #Stdnts)) / (S.D.^3) ] '.
- ' Dis.F. : Discrimination Factor: A Standard for '.
- 'evaluating the problem according to a Criterion '.
- ' [Applied Criterion in %27 Upper Students - '.
- 'Applied the same Criterion in %27 Lower Students] '.
- ' 1st Criterion for Sorting the Students: '.
- 'Sum of Partial Credit Awarded / Total Number of Tries '.
- ' 2nd Criterion for Sorting the Students: '.
- 'Total number of Correct Answers / Total Number of Tries'.
- '
';
-
- $r->print($Ptr);
-
- $r->print('Output CSV format: print(' checked'); }
- $r->print('>');
-
- $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();
- }
- else {
- $r->print("Unable to tie hash to db file");
- }
- }
- else {
- if (tie(%CachData,'GDBM_File',$CacheDB,&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();
- }
- else {
- $r->print("Unable to tie hash to db file");
+# ------ Dump the Student's DB file and handling the data for statistics table
+sub ExtractStudentData {
+ my ($cache,$name)=@_;
+ my %discriminantFactor;
+ my @list=();
+
+ my $totalTries = 0;
+ my $totalAwarded = 0;
+ my $tempProblemOrder=0;
+ foreach my $sequence (split(':', $cache->{'orderedSequences'})) {
+ if($cache->{'ProblemStatisticsMap'} ne 'All Maps' &&
+ $cache->{'ProblemStatisticsMap'} ne $cache->{$sequence.':title'}) {
+ next;
}
- }
-
-# $r->print('Total instances of the problems : '.($p_count*($#students+1)));
- untie(%CachData);
- untie(%GraphDat);
-}
+ my $Dis = '';
+ 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'}='-';
+ }
-# ------------------------------------- Find the section of student in a course
-
-sub usection {
- my ($udom,$unam,$courseid,$ActiveFlag)=@_;
- $courseid=~s/\_/\//g;
- $courseid=~s/^(\w)/\/$1/;
- foreach (split(/\&/,&Apache::lonnet::reply('dump:'.
- $udom.':'.$unam.':roles',
- &Apache::lonnet::homeserver($unam,$udom)))){
- 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));
- if ( $ActiveFlag ne 'Any' ) {
- my $now=time;
- my $notactive=0;
- if ($start) {
- if ($now<$start) { $notactive=1; }
- }
- if ($end) {
- if ($now>$end) { $notactive=1; }
- }
- if ((($ActiveFlag eq 'Expired') && $notactive == 1) ||
- (($ActiveFlag eq 'Active') && $notactive == 0 ) ) {
- return $section;
- }
- else { return '-1'; }
- }
- return $section;
- }
- }
- return '-1';
-}
+ # 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 $time=0;
+ my $awarded=0;
+ my $code='U';
+
+ $awarded = $cache->{$name.
+ "$Version:$problem:resource.".
+ "$part.awarded"};
+ $partData{$part.':awarded'} = ($awarded) ? $awarded : 0;
+ $totalAwarded += $awarded;
+
+ $tries = $cache->{$name.":$Version:$problem".
+ ":resource.$part.tries"};
+ $partData{$part.':tries'} = ($tries) ? $tries : 0;
+ $partData{$part.':wrong'} = $partData{$part.':tries'};
+ $totalTries += $tries;
+
+ my $val = $cache->{$name.":$Version:$problem".
+ ":resource.$part.solved"};
+ if ($val eq 'correct_by_student') {$code = 'C';}
+ elsif ($val eq 'correct_by_override') {$code = 'O';}
+ elsif ($val eq 'incorrect_attempted') {$code = 'I';}
+ elsif ($val eq 'incorrect_by_override'){$code = 'I';}
+ elsif ($val eq 'excused') {$code = 'x';}
+ $partData{$part.':code'}=$code;
+
+ if($partData{$part.':wrong'} ne 0 &&
+ ($code eq 'C' || $code eq 'O')) {
+ $partData{$part.':wrong'}--;
+ }
+ }
+ }
+ # Loop through all the parts for the current problem in the
+ # correct order and prepare the output
+ foreach (split(/\:/,$cache->{$sequence.':'.$problemID.
+ ':parts'})) {
+ my $Yes = 0;
+ if($partData{$_.':code'} eq 'C' ||
+ $partData{$_.':code'} eq 'O') {
+ $Yes=1;
+ }
+ #my $ptr = "$hash{'title_'.$ResId}";
+ my $ptr = $tempProblemOrder.'&'.$problemID;
-# ------ Dump the Student's DB file and handling the data for statistics table
-sub ExtractStudentData {
- my $student=shift;
- my ($sname,$sdom) = split( /\:/, $student );
- my %result = &Apache::lonnet::dump($cid,$sdom,$sname);
- my $ResId;
- my $PrOrd;
- my $Dis = '';
- my $Code;
- my $Tries;
- my $ParCr;
- my $TotalTries = 0;
- my $TotalOpend = 0;
- my $ProbSolved = 0;
- my $ProbTot = 0;
- my $TimeTot = 0;
- my $TotParCr = 0;
- my $Wrongs;
- my %TempHash;
- my $Version;
- my $LatestVersion;
- my $SecLimit;
- my $MapLimit;
- my ($temp)=keys(%result);
- unless ($temp=~/^error\:/) {
- foreach my $CurCol(@cols) {
- ($PrOrd,$ResId)=split(/\:/,$CurCol);
- if ( !$CurCol ) { next; }
- $ResId=~/(\d+)\.(\d+)/;
- my $MapId=$1;
- my $PrbId=$2;
- my $MapOrg = $hash{'map_id_'.$MapId};
- my $Map = &Apache::lonnet::declutter($MapOrg);
- if ( $CurMap ne 'All Maps' ) {
- my ( $ResMap, $NameMap ) = split(/\=/,$CurMap);
- if ( $Map ne $ResMap ) { next; }
- }
- my $meta=$hash{'src_'.$ResId};
- my $PartNo = 0;
- $Dis .= ':';
- undef %TempHash;
-
- foreach (split(/\,/,&Apache::lonnet::metadata($meta,'keys'))) {
- if ($_=~/^stores\_(\w+)\_tries$/) {
- my $Part=&Apache::lonnet::metadata($meta,$_.'.part');
- if ( $TempHash{"$Part"} eq '' ) {
- $TempHash{"$Part"} = $Part;
- $TempHash{$PartNo}=$Part;
- $TempHash{"$Part.Code"} = 'U';
- $TempHash{"$Part.PrOrd"} = $PrOrd+$PartNo;
- $PartNo++;
- }
- #my $Part=&Apache::lonnet::metadata($meta,$_.'.part');
- }
- }
- &Apache::lonnet::declutter( $hash{'src_'.$ResId} );
- my $URI = $hash{'src_'.$ResId};
- my $Prob = $Map.'___'.$PrbId.'___'.
- &Apache::lonnet::declutter($URI);
- $Code='U';
- $Tries = 0;
- $ParCr = 0;
- $Wrongs = 0;
- $LatestVersion = $result{"version:$Prob"};
- if ( $LatestVersion ) {
- for ( my $Version=1; $Version<=$LatestVersion; $Version++ ) {
- my $vkeys = $result{"$Version:keys:$Prob"};
- my @keys = split(/\:/,$vkeys);
- foreach my $Key (@keys) {
- if (($Key=~/\.(\w+)\.solved$/) && ($Key!~/^\d+\:/)) {
- my $Part = $1;
- $Tries = $result{"$Version:$Prob:resource.$Part.tries"};
- $ParCr = $result{"$Version:$Prob:resource.$Part.awarded"};
- my $Time = $result{"$Version:$Prob:timestamp"};
- $TempHash{"$Part.Time"} = ($Time) ? $Time : 0;
- $TempHash{"$Part.Tries"} = ($Tries) ? $Tries : 0;
- $TempHash{"$Part.ParCr"} = ($ParCr) ? $ParCr : 0;
- $TotalTries += $TempHash{"$Part.Tries"};
- $TotParCr += $TempHash{"$Part.ParCr"};
- my $Val = $result{"$Version:$Prob:resource.$Part.solved"};
- if ( $Val eq 'correct_by_student' )
- { $Wrongs = $Tries - 1; $Code = 'C'; }
- elsif ( $Val eq 'correct_by_override' )
- { $Wrongs = $Tries - 1; $Code = 'O'; }
- elsif ( $Val eq 'incorrect_attempted' ||
- $Val eq 'incorrect_by_override' )
- { $Wrongs = $Tries; $Code = 'I'; }
- $TempHash{"$Part.Code"} = $Code;
- $TempHash{"$Part.Wrongs"} = $Wrongs;
- }
- }
- }
- for ( my $n = 0; $n < $PartNo; $n++ ) {
- my $part = $TempHash{$n};
- my $Yes = 0;
- if ( $TempHash{$part.'.Code'} eq 'C' ||
- $TempHash{$part.'.Code'} eq 'O' )
- {$ProbSolved++;$Yes=1;}
-
- # my $ptr = "$hash{'title_'.$ResId}";
- my $ptr = $TempHash{$part.'.PrOrd'}.'&'.$ResId;
-
- if ( $PartNo > 1 ) {
- $ptr .= "*(part $part)";
- $Dis .= '&';
- }
- my $Fac = ($TempHash{"$part.Tries"}) ?
- ($TempHash{"$part.ParCr"}/$TempHash{"$part.Tries"}) : 0;
- my $DisF;
- if ( $Fac > 0 && $Fac < 1 ) {
- $DisF = sprintf( "%.4f", $Fac );
- }
- else {$DisF = $Fac;}
-# $DisF .= '+'.$TempHash{"$part.Time"};33333333
- $TimeTot += $TempHash{"$part.Time"};
- $Dis .= $TempHash{$part.'.PrOrd'}.'='.$DisF.'+'.$Yes;
- $ptr .= "&$TempHash{$part.'.Tries'}".
- "&$TempHash{$part.'.Wrongs'}".
- "&$TempHash{$part.'.Code'}";
- push (@list, $ptr);
- $TotalOpend++;
- $ProbTot++;
- }
+ if($_ > 1) {
+ $ptr .= "*(part $_)";
+ $Dis .= '&';
+ }
+ my $Fac = ($partData{$_.':Tries'}) ?
+ ($partData{$_.':awarded'}/$partData{$_.':tries'}) : 0;
+ my $DisF;
+ if($Fac > 0 && $Fac < 1) {
+ $DisF = sprintf( "%.4f", $Fac );
+ } else {
+ $DisF = $Fac;
+ }
+ $Dis .= $tempProblemOrder.'='.$DisF.'+'.$Yes;
+ $ptr .= '&'.$partData{$_.'.Tries'}.
+ '&'.$partData{$_.'.Wrongs'}.
+ '&'.$partData{$_.'.Code'};
+ push (@list, $ptr);
+ $tempProblemOrder++;
}
- #else {
- #for(my $n=0; $n<$PartNo; $n++) {
- # push (@list, "$TempHash{'0'.'.PrOrd'}.':'.$ResId:0:0:U");
- # $ProbTot++;
- #}
- #}
}
- if ( $TotalTries ) {
- my $DisFac = ( $TotalTries ) ? ($TotParCr/$TotalTries) : 0;
+ if($totalTries) {
+ my $DisFac = ($totalAwarded/$totalTries);
my $DisFactor = sprintf( "%.4f", $DisFac );
- $DiscFac{$DisFactor}=$Dis;
- #my $time;
- #if ($ProbSolved){
- #$time = int(($TimeTot/$ProbSolved)-10000000);
- #}
- #$DiscFac{($DisFactor.':'.$sname.':'.$ProbTot.':'.$TotalOpend.':'.
- # $TotalTries.':'.$ProbSolved.':'.$time)}=$Dis;
+ $discriminantFactor{$DisFactor}=$Dis;
}
}
- #$r->print($sname.' PrCr= '.$TotParCr.' Slvd= '.$ProbSolved.' Tries='.$TotalTries.' ');
-}
-
-# ------------------------------------------------------------ Build page table
-sub tracetable {
- my ($rid,$beenhere)=@_;
- my $IsMap=0;
- $rid=~/(\d+)\.(\d+)/;
- $maps{&Apache::lonnet::declutter($hash{'map_id_'.$1})}='';#$hash{'title_'.$rid};
- #$maps{$HWN}=$hash{'title_'.$rid};
- unless ($beenhere=~/\&$rid\&/) {
- $beenhere.=$rid.'&';
- if (defined($hash{'is_map_'.$rid})) {
- my $cmap=$hash{'map_type_'.$hash{'map_pc_'.$hash{'src_'.$rid}}};
- if ( $cmap eq 'sequence' || $cmap eq 'page' ) {
- $cols[$#cols+1]=0;
- $P_Order++;
- $HWN=$P_Order;
- $mapsort{$HWN} = $rid.':';
- $IsMap=1;
-
- #$maps{&Apache::lonnet::declutter($hash{'src_'.$rid})}=
- # $hash{'title_'.$rid};
- }
- if ((defined($hash{'map_start_'.$hash{'src_'.$rid}})) &&
- (defined($hash{'map_finish_'.$hash{'src_'.$rid}}))) {
- my $frid=$hash{'map_finish_'.$hash{'src_'.$rid}};
-
- &tracetable($hash{'map_start_'.$hash{'src_'.$rid}},
- '&'.$frid.'&');
-
- $cols[$#cols+1]=($P_Order+1).':'.$frid;
-
- my $meta=$hash{'src_'.$frid};
- my $PartNo = 0;
- my $Part;
- # if ($IsMap==0){
- if ($meta) {
- if ($meta=~/\.(problem|exam|quiz|assess|survey|form)$/) {
- foreach (split(/\,/,&Apache::lonnet::metadata($meta,'keys'))) {
- if ($_=~/^stores\_(\w+)\_tries$/) {
- $Part=&Apache::lonnet::metadata($meta,$_.'.part');
- $P_Order++;
- $mapsort{$HWN} .= '&'.$P_Order;
- $PartNo++;
- #$r->print(' '.$PartNo.'---'.$P_Order);
- }
- foreach my $K(split(/\,/,&Apache::lonnet::metadata($meta,'packages'))) {
- if ($K=~/^optionresponse\_($Part)\_(\w+)$/) {
- #$r->print(' '.$_.'...'.$P_Order.'---'.$Part);
- $OpResp{$P_Order}="$frid:$Part";
- }
- }
- }
- }
- }
- }
- # }
- } else {
- $cols[$#cols+1]=($P_Order+1).':'.$rid;
- my $meta=$hash{'src_'.$rid};
- my $PartNo = 0;
- if ($meta) {
- if ($meta=~/\.(problem|exam|quiz|assess|survey|form)$/) {
- foreach my $Key(split(/\,/,&Apache::lonnet::metadata($meta,'keys'))) {
- if ($Key=~/^stores\_(\w+)\_tries$/) {
- my $Part=&Apache::lonnet::metadata($meta,$Key.'.part');
- $P_Order++;
- $mapsort{$HWN} .= '&'.$P_Order;
- $PartNo++;
- foreach (split(/\,/,&Apache::lonnet::metadata($meta,'packages'))) {
- if ($_=~/^optionresponse\_($Part)\_(\w+)$/) {
- #$r->print(' '.$_.'...'.$P_Order.'---'.$Part);
- $OpResp{$P_Order}="$rid:$Part";;
- }
-
- }
-
- }
- }
- }
- }
- }
- if (defined($hash{'to_'.$rid})) {
- foreach (split(/\,/,$hash{'to_'.$rid})){
- &tracetable($hash{'goesto_'.$_},$beenhere);
- }
- }
- }
+ return (\%discriminantFactor, \@list);
}
sub MySort {
@@ -981,73 +608,31 @@ sub MySort {
}
}
-sub Create_PrgWin {
-#----------- Create progress
- $r->print(<
- popwin=open('','popwin','width=400,height=100');
- popwin.document.writeln(''+
- 'LON-CAPA Statistics'+
- '
Computation Progress
'+
- ''+
- '');
- popwin.document.close();
-
-ENDPOP
-
- $r->rflush();
-}
-
-
-sub Update_PrgWin {
-#----------- update progress
- my $index = shift;
- $r->print('');
- $r->rflush();
-}
-
-sub Close_PrgWin {
-#--------------------- close Progress Line
- $r->print('');
- $r->rflush();
-}
-
-sub Build_Statistics {
- &Create_PrgWin();
-# ---------------------------- Gathering the Data of students' tries
- for (my $index=0;$index<=$#students;$index++) {
- &Update_PrgWin($index);
- &ExtractStudentData($students[$index]);
- }
-
-# -------------------- sorting the Data
- $r->print('');
-
- @list = sort (@list);
-
- &Discriminant();
+sub BuildStatisticsTable {
+ my ($cache,$discriminantFactor,$list,$headings)=@_;
- $OpSel2='';
- $OpSel1='selected';
-
- $p_count = 0;
- my $nIdx = 0;
- my $dummy;
+ my $p_count = 0;
+ my $nIndex = 0;
+ my $dummy;
my $p_val;
my $ResId;
- my $NoElements = $#list + 1;
-#-------------------------------- loop for data representation
- foreach (sort keys %mapsort) {
+ my $NoElements = scalar @$list;
+
+ foreach my $sequence (split(':', $cache->{'orderedSequences'})) {
+ if($cache->{'ProblemStatisticsMap'} ne 'All Maps' &&
+ $cache->{'ProblemStatisticsMap'} ne $cache->{$sequence.':title'}) {
+ next;
+ }
+
+ &CreateProblemStatisticsTableHeading($cache->{'DisplayFormat'},
+ $cache->{$sequence.':source'},
+ $cache->{$sequence.':title'},
+ $headings);
my ($Hid,$pr)=split(/\:/,$mapsort{$_});
my @lpr=split(/\&/,$pr);
- &CreateTable(1,$Hid);
for (my $i=1; $i<=$#lpr; $i++) {
my %storestats=();
- my ($PrOrd,$Prob,$Tries,$Wrongs,$Code)=split(/\&/,$list[$nIdx]);
+ my ($PrOrd,$Prob,$Tries,$Wrongs,$Code)=split(/\&/,$list->[$nIndex]);
my $Temp = $Prob;
my $MxTries = 0;
my $TotalTries = 0;
@@ -1058,7 +643,7 @@ sub Build_Statistics {
my @StdLst;
while ( $PrOrd == $lpr[$i] )
{
- $nIdx++;
+ $nIndex++;
$StdNo++;
$StdLst[ $StdNo ] = $Tries;
$TotalTries += $Tries;
@@ -1067,7 +652,7 @@ sub Build_Statistics {
elsif( $Code eq 'I' ) { $Incorrect++; }
elsif( $Code eq 'O' ) { $Override++; }
elsif( $Code eq 'U' ) { $StdNo--; }
- ($PrOrd,$Prob,$Tries,$Wrongs,$Code)=split(/\&/,$list[$nIdx]);
+ ($PrOrd,$Prob,$Tries,$Wrongs,$Code)=split(/\&/,$list->[$nIndex]);
}
$p_count++;
@@ -1130,8 +715,8 @@ sub Build_Statistics {
}
#--------------------- Compute the Discrimination Factors
- my ($Up1,$Up2)=split(/\:/,$DisUp{$lpr[$i]});
- my ($Lw1,$Lw2)=split(/\:/,$DisLow{$lpr[$i]});
+ my ($Up1,$Up2)=split(/\:/,':');#jason$DisUp->{$lpr[$i]});
+ my ($Lw1,$Lw2)=split(/\:/,':');#jason$DisLow->{$lpr[$i]});
my $Dis1 = $Up1 - $Lw1;
my $Dis2 = $Up2 - $Lw2;
my $_D1 = sprintf("%.2f", $Dis1);
@@ -1155,16 +740,16 @@ sub Build_Statistics {
&Apache::lonnet::put('resevaldata',\%storestats,$1,$2);
}
#-------------------------------- Row of statistical table
- if ( $DiscFlag == 0 ) {
- &TableRow($join,$i,($p_count-1));
- }
+ &TableRow($cache,$join,$i,($p_count-1));
}
- &CloseTable();
+ &CloseTable($cache);
}
&Close_PrgWin();
}
+=pod
sub Cache_Statistics {
+ my ($cache)=@_;
my @list = ();
my $Useful;
my $UnUseful;
@@ -1172,7 +757,7 @@ sub Cache_Statistics {
my %myHeader = reverse( %Header );
$Pos = $myHeader{$ENV{'form.sort'}};
if ($Pos > 0) {$Pos++;}
- $p_count = 0;
+ my $p_count = 0;
foreach my $key( keys %CachData) {
my @Temp=split(/\&/,$CachData{$key});
if ( $Pos == 0 ) {
@@ -1187,37 +772,37 @@ sub Cache_Statistics {
@list = sort MySort (@list);
- my $nIdx=0;
+ my $nIndex=0;
if ( $Pos == 0 ) {
foreach (sort keys %mapsort) {
my ($Hid,$pr)=split(/\:/,$mapsort{$_});
- &CreateTable(1,$Hid);
+ &CreateProblemStatisticsTableHeading($cache,1,$Hid);
my @lpr=split(/\&/,$pr);
for (my $i=1; $i<=$#lpr; $i++) {
- my($Pre, $Post) = split(/\@/,$list[$nIdx]);
+ my($Pre, $Post) = split(/\@/,$list[$nIndex]);
#$r->print(' '.$Pre.'---'.$Post);
- &TableRow($Post,$i,$nIdx);
- $nIdx++;
+ &TableRow($cache,$Post,$i,$nIndex);
+ $nIndex++;
}
- &CloseTable();
+ &CloseTable($cache);
}
}
else {
- &CreateTable(0);
- for ( my $nIdx = 0; $nIdx < $p_count; $nIdx++ ) {
- my($Pre, $Post) = split(/\@/,$list[$nIdx]);
- &TableRow($Post,$nIdx,$nIdx);
+ &CreateProblemStatisticsTableHeading($cache,0);
+ for ( my $nIndex = 0; $nIndex < $p_count; $nIndex++ ) {
+ my($Pre, $Post) = split(/\@/,$list[$nIndex]);
+ &TableRow($cache,$Post,$nIndex,$nIndex);
}
- &CloseTable();
+ &CloseTable($cache);
}
}
-
+=cut
sub TableRow {
- my ($Str,$Idx,$RealIdx)=@_;
+ my ($cache,$Str,$Idx,$RealIdx)=@_;
my($PrOrd,$Temp,$StdNo,$TotalTries,$MxTries,$Avg,$YES,$Override,
$Wrng,$DoD,$SD,$Sk,$_D1,$_D2,$Prob)=split(/\&/,$Str);
- if ($ENV{'form.showcsv'}) {
+ if($cache->{'DisplayFormat'} eq 'Display CSV Format') {
my ($ResId,$Dummy)=split(/\*/,$Prob);
my $Ptr = "\n".' '.
"\n".'"'.($RealIdx+1).'",'.
@@ -1236,417 +821,1077 @@ sub TableRow {
"\n".'"'.$_D1.'",'.
"\n".'"'.$_D2.'"';
$r->print("\n".$Ptr);
- }
- else{
+ } else {
my $Ptr = "\n".'
'.
"\n".'
'.($RealIdx+1).'
'.
# "\n".'
'.$PrOrd.$Temp.'
'.
"\n".'
'.$Temp.'
'.
- "\n".'
'.$StdNo.'
'.
- "\n".'
'.$TotalTries.'
'.
- "\n".'
'.$MxTries.'
'.
- "\n".'
'.$Avg.'
'.
- "\n".'
'.$YES.'
'.
- "\n".'
'.$Override.'
'.
- "\n".'
'.$Wrng.'
'.
- "\n".'
'.$DoD.'
'.
- "\n".'
'.$SD.'
'.
- "\n".'
'.$Sk.'
'.
- "\n".'
'.$_D1.'
'.
- "\n".'
'.$_D2.'
';
+ "\n".'
'.$StdNo.'
'.
+ "\n".'
'.$TotalTries.'
'.
+ "\n".'
'.$MxTries.'
'.
+ "\n".'
'.$Avg.'
'.
+ "\n".'
'.$YES.'
'.
+ "\n".'
'.$Override.'
'.
+ "\n".'
'.$Wrng.'
'.
+ "\n".'
'.$DoD.'
'.
+ "\n".'
'.$SD.'
'.
+ "\n".'
'.$Sk.'
'.
+ "\n".'
'.$_D1.'
'.
+ "\n".'
'.$_D2.'
';
$r->print("\n".$Ptr.'
' );
}
$GraphDat{$RealIdx}=$DoD.':'.$Wrng;
}
-# ------------------------------------------- Prepare data for Graphical chart
+sub StatusOptions {
+ my ($cache)=@_;
+
+ my $Status = $cache->{'Status'};
+ my $OpSel1 = '';
+ my $OpSel2 = '';
+ my $OpSel3 = '';
+
+ if($Status eq 'Any') { $OpSel3 = ' selected'; }
+ elsif($Status eq 'Expired' ) { $OpSel2 = ' selected'; }
+ else { $OpSel1 = ' selected'; }
+
+ my $Ptr = '';
+ $Ptr .= '
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 .= '
';
+
+ return $Ptr;
+}
+
+#---- END Problem Statistics Web Page ----------------------------------------
+
+#---- Problem Statistics Graph Web Page --------------------------------------
sub GetGraphData {
- my $ylab = shift;
- my $Col;
+ my ($whichGraph, $courseID)=@_;
+ my $Col=0;
+ my $graphTitle='';
my $data='';
my $count = 0;
my $Max = 0;
- my $cid=$ENV{'request.course.id'};
+ my $graphData='Graph data does not exist.';
my $GraphDB = "/home/httpd/perl/tmp/$ENV{'user.name'}".
- "_$ENV{'user.domain'}_$cid\_graph.db";
- foreach (keys %GraphDat) {delete $GraphDat{$_};}
- if (-e "$GraphDB") {
- if (tie(%GraphDat,'GDBM_File',"$GraphDB",&GDBM_READER,0640)) {
- if ( $ylab eq 'DoDiff Graph' ) {
- $ylab = 'Degree-of-Difficulty';
+ "_$ENV{'user.domain'}_$courseID\_graph.db";
+ if(-e $GraphDB) {
+ if(tie(%GraphDat,'GDBM_File',"$GraphDB",&GDBM_READER,0640)) {
+ if($whichGraph eq 'DiffGraph') {
+ $graphTitle = 'Degree-of-Difficulty';
$Col = 0;
- }
- else {
- $ylab = 'Wrong-Percentage';
+ } else {
+ $graphTitle = 'Wrong-Percentage';
$Col = 1;
}
foreach (sort NumericSort keys %GraphDat) {
my @Temp=split(/\:/,$GraphDat{$_});
my $inf = $Temp[$Col];
- if ( $Max < $inf ) {$Max = $inf;}
+ if($Max < $inf) {
+ $Max = $inf;
+ }
$data .= $inf.',';
$count++;
}
- if ( $Max > 1 ) {
+ if($Max > 1) {
$Max += (10 - $Max % 10);
$Max = int($Max);
- }
- else { $Max = 1; }
+ } else {
+ $Max = 1;
+ }
untie(%GraphDat);
- my $Course = $ENV{'course.'.$cid.'.description'};
+ my $Course = $ENV{'course.'.$courseID.'.description'};
$Course =~ s/\ /"_"/eg;
- $GData=$Course.'&'.'Problems'.'&'.$ylab.'&'.$Max.'&'.$count.'&'.$data;
- }
- else {
- $r->print("Unable to tie hash to db file");
+ $graphData = $Course.'&'.'Problems'.'&'.$graphTitle.'&'.$Max.'&';
+ $graphData .= $count.'&'.$data;
+ } else {
+ $graphData = "Unable to tie hash to db file";
}
}
+
+ return $graphData;
}
+#---- END Problem Statistics Graph Web Page ----------------------------------
-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 %OpResp;
- undef %ConceptData;
- undef $CurMap;
- undef $CurSec;
- undef $CurStu;
- undef $p_count;
- undef $Pos;
- undef $GData;
- $DiscFlag=0;
- $P_Order=100000;
- $HWN=$P_Order;
-}
-
-# my $CacheDB = "/home/httpd/perl/tmp/$ENV{'user.name'}".
-# "_$ENV{'user.domain'}_$cid\_classlist.db";
-# if (-e "$CacheDB") {
-# if (tie(%students,'GDBM_File',"$CacheDB",&GDBM_READER,0640)) {
-# &CachClassList();
-# }
-# else {
-# $r->print("Unable to tie hash to db file");
-# }
-# }
-# else {
-# if (tie(%students,'GDBM_File',$CacheDB,&GDBM_WRCREAT,0640)) {
-# &MakeClassList();
-# }
-# else {
-# $r->print("Unable to tie hash to db file");
-# }
-# }
-# untie(%students);
+#---- Problem Analysis Web Page ----------------------------------------------
+
+sub IntervalOptions {
+ my ($cache)=@_;
+ my $interval = 1;
+ for(my $n=1; $n<=7; $n++) {
+ if($cache->{'Interval'} == $n) {
+ $interval = $n;
+ }
+ }
-sub ClassList {
+ my $Ptr = ' Select number of intervals'."\n".
+ ''."\n";
- &GetStatus();
+ return $Ptr;
+}
- $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)) {
-# my %students = &Apache::lonnet::dump('classlist',$cdom,$cnum);
-# $Apache::lonxml::debug=1;
-# &Apache::lonhomework::showhash(%students);
-# $Apache::lonxml::debug=0;
-# my $StudNo = 0;
-# my $now=time;
-# my ($temp)=keys(%students);
-# unless ($temp=~/^error\:/) {
-# foreach my $KeyPoint(sort keys(%students)) {
-
-
- my $classlst=&Apache::lonnet::reply('dump:'.$cdom.':'.$cnum.':classlist',$chome);
-
- my $StudNo = 0;
- my $now=time;
- unless ($classlst=~/^error\:/) {
- foreach my $KeyPoint(sort split(/\&/,$classlst)) {
- my ($name,$value)=split(/\=/,$KeyPoint);
- my ($end,$start)=split(/\:/,&Apache::lonnet::unescape($value));
- my $active=1;
- my $Status=$ENV{'form.status'};
- $Status = ($Status) ? $Status : 'Active';
- if ( ( ($end) && $now > $end ) &&
- ( ($Status eq 'Active') ) ) { $active=0; }
-
- if ( ($Status eq 'Expired') &&
- ($end == 0 || $now < $end) ) { $active=0; }
-
- if ($active) {
- my $thisindex=$#students+1;
- $name=&Apache::lonnet::unescape($name);
- $students[$thisindex]=$name;
- my ($sname,$sdom)=split(/\:/,$name);
- my $ssec=&usection($sdom,$sname,$cid,$Status);
- if ($ssec==-1 || $ssec eq 'adm' ) {next;}
- $ssec=($ssec) ? $ssec : '(none)';
- #$ssec=(int($ssec)) ? int($ssec) : $ssec;
- $section{$ssec}=$ssec;
- if ($CurSec eq 'All Sections' || $ssec eq $CurSec) {
- $students[$StudNo]=$name;
- $StuBox{$sname}=$sdom;
- }
- $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++;
-# }
-# my $c=1;
-# foreach (sort keys %OpResp) {
-# $r->print(' '.$c.')'.$_.' ... '.$OpResp{$_}.' ... '.$hash{'src_'.$OpResp{$_}});
-# $c++;
-# }
+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";
+
+ return $Str;
+}
+
+#---- END Problem Analysis Web Page ------------------------------------------
+
+#---- Student Assessment Web Page --------------------------------------------
+
+sub MapOptions {
+ my ($cache, $page)=@_;
+ my $Ptr = '
';
+ $Ptr .= '
Select Map
'."\n";
+ $Ptr .= '
'."\n";
+
+ return $Ptr;
+}
+
+sub StudentOptions {
+ my ($students, $selectedName)=@_;
+
+ my $Ptr ='