# The LearningOnline Network with CAPA # (Publication Handler # # $Id: lonproblemanalysis.pm,v 1.1 2002/07/24 14:52:32 stredwic Exp $ # # Copyright Michigan State University Board of Trustees # # This file is part of the LearningOnline Network with CAPA (LON-CAPA). # # LON-CAPA is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # LON-CAPA is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with LON-CAPA; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # /home/httpd/html/adm/gpl.txt # # http://www.lon-capa.org/ # # (Navigate problems for statistical reports # YEAR=2001 # 5/5,7/9,7/25/1,8/11,9/13,9/26,10/5,10/9,10/22,10/26 Behrouz Minaei # 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,5/26,7/16 Behrouz Minaei # ### package Apache::lonproblemanalysis; use strict; use Apache::lonnet(); use GDBM_File; sub BuildProblemAnalysisPage { my ($cacheDB)=@_; my %cache; my $Str = ''; unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) { $Str .= 'Unable to tie database.'; return $Str; } $Str .= &IntervalOptions($cache{'Interval'}); $Str .= &OptionResponseTable($cache{'OptionResponses'}); untie(%cache); return $Str; } sub BuildAnalyzePage { my ($cacheDB, $students, $courseID)=@_; my $Str = ''; my %cache; unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) { $Str .= 'Unable to tie database.'; return $Str; } my $uri = $cache{'AnalyzeURI'}, my $part = $cache{'AnalyzePart'}, my $problem = $cache{'AnalyzeProblem'}, my $title = $cache{'AnalyzeTitle'}, my $interval = $cache{'Interval'}, my %ConceptData; $ConceptData{"Interval"} = $interval; #Initialize the option response true answers my ($Concepts, $foil_to_concept, $answer) = &InitAnalysis($uri, $part, $problem, $students->[0], $courseID); #compute the intervals &Interval($part, $problem, $interval, $Concepts, \%ConceptData); $title =~ s/\ /"_"/eg; $Str .= '
'.$uri.''; #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, $answer); } &Close_PrgWin(); $Str .= '
'; for (my $k=0; $k<$interval; $k++ ) { $Str .= &DrawGraph($k, $title, $Concepts, \%ConceptData); } for (my $k=0; $k<$interval; $k++ ) { $Str .= &DrawTable($k, $Concepts, \%ConceptData); } #$Apache::lonxml::debug=1; #&Apache::lonhomework::showhash(%ConceptData); #$Apache::lonxml::debug=0; my $Answ=&Apache::lonnet::ssi($uri); $Str .= '
Here you can see the Problem:
'.$Answ; untie(%cache); return $Str; } #---- Problem Analysis Web Page ---------------------------------------------- sub IntervalOptions { my ($selectedInterval)=@_; my $interval = 1; for(my $n=1; $n<=7; $n++) { if($selectedInterval == $n) { $interval = $n; } } my $Ptr = '
Select number of intervals'."\n". ''."\n"; return $Ptr; } sub OptionResponseTable { my ($optionResponses)=@_; my $Str = ''; $Str .= '
Option Response Problems in this course:'."\n"; $Str .= '

'."\n"; $Str .= ""; $Str .= ''."\n"; my $number=1; foreach (split(':::', $optionResponses)) { my ($uri,$title,$part,$problem)=split('::',$_); my $Temp = ''.$title.''; $Str .= ''; $Str .= ''; $Str .= ''; $Str .= ''; $Str .= ''."\n"; $number++; } $Str .= '
\# Problem Title Resource Analysis
'.$number.' '.$Temp.' '.$uri.'
'."\n"; return $Str; } #---- END Problem Analysis Web Page ------------------------------------------ #---- Analyze Web Page ------------------------------------------------------- #restore the student submissions and finding the result sub OpStatus { my ($problem, $student, $courseID, $ConceptData, $foil_to_concept, $Answer)=@_; 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", $foil_to_concept->{$_}, $time, $ConceptData); } else { &Decide("false", $foil_to_concept->{$_}, $time, $ConceptData);} } } } } } } } sub DrawGraph { my ($k,$Src,$Concepts,$ConceptData)=@_; my $Max=0; my @data1; my @data2; # Adjust Data and find the Max for (my $n=0; $n<(scalar @$Concepts); $n++ ) { my $tmp=$Concepts->[$n]; $data1[$n]=$ConceptData->{$tmp.'.'.$k.'.true'}; $data2[$n]=$ConceptData->{$tmp.'.'.$k.'.false'}; my $Sum=$data1[$n]+$data2[$n]; if($Max < $Sum) { $Max=$Sum; } } for (my $n=0; $n<(scalar @$Concepts); $n++ ) { if ($data1[$n]+$data2[$n]<$Max) { $data2[$n]+=$Max-($data1[$n]+$data2[$n]); } } my $P_No = (scalar @data1); if($Max > 1) { $Max += (10 - $Max % 10); $Max = int($Max); } else { $Max = 1; } my $Titr=($ConceptData->{'Interval'}>1) ? $Src.'_interval_'.($k+1) : $Src; # $GData=$Titr.'&Concepts'.'&'.'Answers'.'&'.$Max.'&'.$P_No.'&'.$data1.'&'.$data2; my $GData = ''; $GData = $Titr.'&Concepts&Answers&'.$Max.'&'.$P_No.'&'; $GData .= (join(',',@data1)).'&'.(join(',',@data2)); return ''; } sub DrawTable { my ($k,$Concepts,$ConceptData)=@_; my $Max=0; my @data1; my @data2; my $Correct=0; my $Wrong=0; for(my $n=0; $n<(scalar @$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<(scalar @$Concepts); $n++ ) { if ($data1[$n]+$data2[$n]<$Max) { $data2[$n]+=$Max-($data1[$n]+$data2[$n]); } } my $P_No = (scalar @data1); my $Str = ''; # $Str .= '
From: ['.localtime($ConceptData->{'Int.'.($k-1)}); # $Str .= '] To: ['.localtime($ConceptData->{"Int.$k"}).']'; $Str .= "\n".''. "\n".''. "\n".''. "\n".''. "\n".''. "\n".''. "\n".''; for(my $n=0; $n<(scalar @$Concepts); $n++ ) { $Str .= ''."\n"; $Str .= ''."\n"; $Str .= ''."\n"; $Str .= ''."\n"; $Str .= ''."\n"; $Str .= ''."\n"; } $Str .= ''; $Str .= '
# Concept Correct Wrong
'.($n+1).''.$Concepts->[$n]; $Str .= ''.$data1[$n].''.$data2[$n].'
From:['.localtime($ConceptData->{'Int.'.$k}); $Str .= '] To: ['.localtime($ConceptData->{'Int.'.($k+1)}-1); $Str .= ']'.$Correct.''.$Wrong.'
'."\n"; return $Str; #$Apache::lonxml::debug=1; #&Apache::lonhomework::showhash(%ConceptData); #$Apache::lonxml::debug=0; } #---- END Analyze Web Page ---------------------------------------------- sub Decide { #deciding the true or false answer belongs to each interval my ($type,$concept,$time,$ConceptData)=@_; my $k=0; while ($time>$ConceptData->{'Int.'.($k+1)} && $k<$ConceptData->{'Interval'}) {$k++;} $ConceptData->{$concept.'.'.$k.'.'.$type}++; return; } sub InitAnalysis { my ($uri,$part,$problem,$student,$courseID)=@_; my ($name,$domain)=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' => $name, 'grade_domain' => $domain, 'grade_courseid' => $courseID, 'grade_symb' => $problem)); # my $Answ=&Apache::lonnet::ssi($URI,('grade_target' => 'analyze')); # (my $garbage,$Answ)=split(/_HASH_REF__/,$Answ,2); my %Answer=(); %Answer=&Apache::lonnet::str2hash($Answ); my $parts=''; foreach my $elm (@{$Answer{'parts'}}) { $parts.= $elm.','; } $parts =~ s/,$//; my @Concepts=(); foreach my $elm (@{$Answer{$parts.'.concepts'}}) { push(@Concepts, $elm); } my %foil_to_concept; foreach my $concept (@Concepts) { foreach my $foil (@{$Answer{$parts.'.concept.'.$concept}}) { $foil_to_concept{$foil} = $concept; #$ConceptData{$foil} = $Answer{$parts.'.foil.value.'.$foil}; } } return (\@Concepts, \%foil_to_concept, \%Answer); } sub Interval { my ($part,$symb,$interval,$Concepts,$ConceptData)=@_; my $Int=$interval; my $due = &Apache::lonnet::EXT('resource.'.$part.'.duedate',$symb); 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<(scalar @$Concepts); $n++ ) { my $tmp=$Concepts->[$n]; $ConceptData->{$tmp.'.'.$i.'.true'}=0; $ConceptData->{$tmp.'.'.$i.'.false'}=0; } } } 1; __END__