# 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 .= "
\#
Problem Title
";
$Str .= '
Resource
Analysis
'."\n";
my $number=1;
foreach (split(':::', $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 ------------------------------------------
#---- 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".'
From:['.localtime($ConceptData->{'Int.'.$k});
$Str .= '] To: ['.localtime($ConceptData->{'Int.'.($k+1)}-1);
$Str .= ']
'.$Correct.'
'.$Wrong.'
';
$Str .= '
'."\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__