'.
- ' #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) ] '.
+#restore the student submissions and finding the result
+sub OpStatus {
+ my ($problem, $student, $courseID)=@_;
+ my ($username,$userdomain)=split(/':'/,$student);
+ my $code='U';
+ my %reshash=&Apache::lonnet::restore($problem, $courseID, $userdomain,
+ $username);
+ my @True = ();
+ my @False = ();
+ my $flag=0;
+ if ($reshash{'version'}) {
+ my $tries=0;
+ &Apache::lonhomework::showhash(%Answer);
+ for (my $version=1;$version<=$reshash{'version'};$version++) {
+ my $time=$reshash{"$version:timestamp"};
+
+ foreach my $key (sort(split(/\:/,$reshash{$version.':keys'}))) {
+ if (($key=~/\.(\w+)\.(\w+)\.submission$/)) {
+ my $Id1 = $1; my $Id2 = $2;
+ #check if this is a repeat submission, if so skip it
+ if ($reshash{"$version:resource.$Id1.previous"}) { next; }
+ #if no solved this wasn't a real submission, ignore it
+ if (!defined($reshash{"$version:resource.$Id1.solved"})) {
+ &Apache::lonxml::debug("skipping ");
+ next;
+ }
+ my $Resp = $reshash{"$version:$key"};
+ my %submission=&Apache::lonnet::str2hash($Resp);
+ foreach (keys %submission) {
+ my $Ansr = $Answer{"$Id1.$Id2.foil.value.$_"};
+ if ($submission{$_}) {
+ if ($submission{$_} eq $Ansr) {
+ &Decide("true",$_,$time );
+ }
+ else {&Decide("false",$_,$time );}
+ }
+ }
+ }
+ }
+ }
+ }
+}
-# ' Dis.F. : Discrimination Factor. [ Sum of Partial Credits Awarded / Total Number of Tries in %27 upper and lower students]'.
- '
';
+#---- END Analyze Web Page ----------------------------------------------
- $r->print($Ptr);
- $r->rflush();
+#---- Problem Statistics Web Page ---------------------------------------
- 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");
- }
+#------- Processing upperlist and lowerlist according to each problem
+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 $nIndex=0;
+ my $nStudent=0;
+ my %Proc=undef;
+ while ($nIndex<$Count) {
+ ($Problem,$tmp)=split(/\=/,$sortedList[$nIndex]);
+ @Dis=split(/\+/,$tmp);
+ my $Temp = $Problem;
+ do {
+ $nIndex++;
+ $nStudent++;
+ $Sum1 += $Dis[0];
+ $Sum2 += $Dis[1];
+ ($Problem,$tmp)=split(/\=/,$sortedList[$nIndex]);
+ @Dis=split(/\+/,$tmp);
+ } 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;
+ $nStudent=0;
}
- 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();
- }
- else {
- $r->print("Unable to tie hash to db file");
+
+ return %Proc;
+}
+
+
+#------- Creating Discimination factor
+sub Discriminant {
+ 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(@discriminantKeys)) {
+ $Count++;
+ if($low < $UpCnt || $Count > $up) {
+ $low++;
+ my $str=$discriminantFactor->{$key};
+ foreach(split(/\:/,$str)){
+ if($_) {
+ if($low<$UpCnt) { push(@LowList,$_); }
+ else { push(@UpList,$_); }
+ }
+ }
}
}
- #$r->print('Total instances of the problems : '.($p_count*($#students+1)));
+ my %DisUp = &ProcessDiscriminant(\@UpList);
+ my %DisLow = &ProcessDiscriminant(\@LowList);
- untie(%CachData);
- untie(%GraphDat);
- untie(%DiscFac);
+ return (\%DisUp, \%DisLow);
}
+sub NumericSort {
+ $a <=> $b;
+}
-# ------------------------------------- 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;
- }
+sub CreateProblemStatisticsTableHeading {
+ my ($displayFormat,$sequenceSource,$sequenceTitle,$headings)=@_;
+ if($displayFormat eq 'Display CSV Format') {
+ $r->print(' "'.$sequenceTitle.'","');
+ $r->print($sequenceSource.'"');
+ return;
}
- return '-1';
+
+ $r->print(' '.$sequenceTitle.'');
+
+ my $Result = "\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 .= '
';
+
+ return $Ptr;
+}
+
+#---- END Problem Statistics Web Page ----------------------------------------
+
+#---- Problem Statistics Graph Web Page --------------------------------------
sub GetGraphData {
- my $Tag = 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 ( $Tag eq 'DoDiff Graph' ) {
- $Tag = '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 {
- $Tag = '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) {
+ $Max += (10 - $Max % 10);
+ $Max = int($Max);
+ } else {
+ $Max = 1;
+ }
untie(%GraphDat);
- my $Course = $ENV{'course.'.$cid.'.description'};
+ my $Course = $ENV{'course.'.$courseID.'.description'};
$Course =~ s/\ /"_"/eg;
- $GData=$Course.'&'.$Tag.'&'.$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 $CurMap;
- undef $CurSec;
- undef $CurStu;
- undef $p_count;
- undef $Pos;
- undef $GData;
- $DiscFlag=0;
- $P_Order=100000;
- $HWN=$P_Order;
-}
-
-
-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;
- my $now=time;
- 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 $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 %reply=&Apache::lonnet::idrget($sdom,$sname);
- #my $reply=&Apache::lonnet::reply('get:'.$sdom.':'.$sname.
- # ':environment:lastname&generation&firstname&middlename',
- # &Apache::lonnet::homeserver($sname,$sdom));
- my $ssec=&usection($sdom,$sname,$cid,$Status);
- 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);
+#---- Problem Analysis Web Page ----------------------------------------------
+
+sub IntervalOptions {
+ my ($cache)=@_;
+ my $interval = 1;
+ for(my $n=1; $n<=7; $n++) {
+ if($cache->{'Interval'} == $n) {
+ $interval = $n;
+ }
}
-# ------------------------------------------------------------- End render page
- else {
- $r->print('
Undefined course sequence
');
+ my $Ptr = ' Select number of intervals'."\n".
+ ''."\n";
+ return $Ptr;
+}
-sub Menu {
- my $InpStr = $ENV{'form.sort'};
- if ( $InpStr eq 'DoDiff Graph' || $InpStr eq '%Wrong Graph' ) {
- &GetGraphData($InpStr);
- $r->print('');
+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 .= '
');
-# ------------------------------- This is going to take a while, produce output
- $r->rflush();
-
- $r->print("\n".''.
- "\n".''.
- "\n".'');
- $r->rflush();
+#---- END Problem Analysis Web Page ------------------------------------------
+
+#---- Student Assessment Web Page --------------------------------------------
+
+sub MapOptions {
+ my ($cache, $page)=@_;
+ my $Ptr = '