--- loncom/homework/lonhomework.pm 2001/11/05 22:49:14 1.62
+++ loncom/homework/lonhomework.pm 2005/01/28 21:08:45 1.195
@@ -1,383 +1,890 @@
+# The LearningOnline Network with CAPA
# The LON-CAPA Homework handler
-# Guy Albertelli
-# 11/30 Gerd Kortemeyer
-# 6/1,8/17,8/18 Gerd Kortemeyer
+#
+# $Id: lonhomework.pm,v 1.195 2005/01/28 21:08:45 albertel 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/
+
package Apache::lonhomework;
use strict;
-use Apache::style;
-use Apache::lonxml;
-use Apache::lonnet;
-use Apache::inputtags;
-use Apache::structuretags;
-use Apache::randomlabel;
-use Apache::response;
-use Apache::hint;
-use Apache::outputtags;
+use Apache::style();
+use Apache::lonxml();
+use Apache::lonnet();
+use Apache::lonplot();
+use Apache::inputtags();
+use Apache::structuretags();
+use Apache::randomlabel();
+use Apache::response();
+use Apache::hint();
+use Apache::outputtags();
+use Apache::caparesponse();
+use Apache::radiobuttonresponse();
+use Apache::optionresponse();
+use Apache::imageresponse();
+use Apache::essayresponse();
+use Apache::externalresponse();
+use Apache::rankresponse();
+use Apache::matchresponse();
+use Apache::chemresponse();
+use Apache::drawimage();
use Apache::Constants qw(:common);
-#use Time::HiRes qw( gettimeofday tv_interval );
+use HTML::Entities();
+use Apache::loncommon();
+use Apache::lonlocal;
+use Time::HiRes qw( gettimeofday tv_interval );
+use Apache::lonnet();
+
+# FIXME - improve commenting
+
-sub BEGIN {
- &Apache::lonxml::register_insert();
+BEGIN {
+ &Apache::lonxml::register_insert();
}
+
+#
+# Decides what targets to render for.
+# Implicit inputs:
+# Various session environment variables:
+# request.state - published - is a /res/ resource
+# uploaded - is a /uploaded/ resource
+# contruct - is a /priv/ resource
+# form.grade_target - a form parameter requesting a specific target
sub get_target {
- if ( $ENV{'request.state'} eq "published") {
- if ( defined($ENV{'form.submitted'})) {
- return ('grade', 'web');
+ &Apache::lonxml::debug("request.state = $ENV{'request.state'}");
+ if( defined($ENV{'form.grade_target'})) {
+ &Apache::lonxml::debug("form.grade_target= $ENV{'form.grade_target'}");
} else {
- return ('web');
+ &Apache::lonxml::debug("form.grade_target ");
}
- } elsif ($ENV{'request.state'} eq "construct") {
- if ( defined($ENV{'form.preview'})) {
- if ( defined($ENV{'form.submitted'})) {
- return ('grade', 'web');
- } else {
- return ('web');
- }
- } else {
- if ( $ENV{'form.problemmode'} eq 'View' ) {
+ if (($ENV{'request.state'} eq "published") ||
+ ($ENV{'request.state'} eq "uploaded")) {
+ if ( defined($ENV{'form.grade_target'} )
+ && ($ENV{'form.grade_target'} eq 'tex')) {
+ return ($ENV{'form.grade_target'});
+ } elsif ( defined($ENV{'form.grade_target'} )
+ && ($Apache::lonhomework::viewgrades eq 'F' )) {
+ return ($ENV{'form.grade_target'});
+ }
+
if ( defined($ENV{'form.submitted'}) &&
- (!defined($ENV{'form.resetdata'})) ) {
- return ('grade', 'web','answer');
+ ( !defined($ENV{'form.resetdata'})) &&
+ ( !defined($ENV{'form.newrandomization'}))) {
+ return ('grade', 'web');
} else {
- return ('web','answer');
+ return ('web');
+ }
+ } elsif ($ENV{'request.state'} eq "construct") {
+ if ( defined($ENV{'form.grade_target'}) ) {
+ return ($ENV{'form.grade_target'});
}
- } elsif ( $ENV{'form.problemmode'} eq 'Edit' ) {
- if ( $ENV{'form.submitted'} eq 'edit' ) {
- return ('modified','edit');
+ if ( defined($ENV{'form.preview'})) {
+ if ( defined($ENV{'form.submitted'})) {
+ return ('grade', 'web');
+ } else {
+ return ('web');
+ }
} else {
- return ('edit');
+ if ( $ENV{'form.problemmode'} eq &mt('View') ||
+ $ENV{'form.problemmode'} eq &mt('Discard Edits and View')) {
+ if ( defined($ENV{'form.submitted'}) &&
+ (!defined($ENV{'form.resetdata'})) &&
+ (!defined($ENV{'form.newrandomization'}))) {
+ return ('grade', 'web','answer');
+ } else {
+ return ('web','answer');
+ }
+ } elsif ( $ENV{'form.problemmode'} eq &mt('Edit') ||
+ $ENV{'form.problemmode'} eq 'Edit') {
+ if ( $ENV{'form.submitted'} eq 'edit' ) {
+ if ( $ENV{'form.submit'} eq &mt('Submit Changes and View') ) {
+ return ('modified','web','answer');
+ } else {
+ return ('modified','edit');
+ }
+ } else {
+ return ('edit');
+ }
+ } else {
+ return ('web');
+ }
}
- } else {
- return ('web');
- }
}
- }
- return ();
+ return ();
}
sub setup_vars {
- my ($target) = @_;
- return ';'
+ my ($target) = @_;
+ return ';'
# return ';$external::target='.$target.';';
}
sub send_header {
- my ($request)= @_;
- $request->print(&Apache::lontexconvert::header());
+ my ($request)= @_;
+ $request->print(&Apache::lontexconvert::header());
# $request->print('');
- $request->print(&Apache::lontexconvert::footer());
+ $request->print(&Apache::lontexconvert::footer());
}
$Apache::lonxml::browse='';
+sub check_ip_acc {
+ my ($acc)=@_;
+ if (!defined($acc) || $acc =~ /^\s*$/) { return 1; }
+ my $allowed=0;
+ my $ip=$ENV{'REMOTE_ADDR'};
+ my $name;
+ foreach my $pattern (split(',',$acc)) {
+ if ($pattern =~ /\*$/) {
+ #35.8.*
+ $pattern=~s/\*//;
+ if ($ip =~ /^\Q$pattern\E/) { $allowed=1; }
+ } elsif ($pattern =~ /(\d+\.\d+\.\d+)\.\[(\d+)-(\d+)\]$/) {
+ #35.8.3.[34-56]
+ my $low=$2;
+ my $high=$3;
+ $pattern=$1;
+ if ($ip =~ /^\Q$pattern\E/) {
+ my $last=(split(/\./,$ip))[3];
+ if ($last <=$high && $last >=$low) { $allowed=1; }
+ }
+ } elsif ($pattern =~ /^\*/) {
+ #*.msu.edu
+ $pattern=~s/\*//;
+ if (!defined($name)) {
+ use Socket;
+ my $netaddr=inet_aton($ip);
+ ($name)=gethostbyaddr($netaddr,AF_INET);
+ }
+ if ($name =~ /\Q$pattern\E$/i) { $allowed=1; }
+ } elsif ($pattern =~ /\d+\.\d+\.\d+\.\d+/) {
+ #127.0.0.1
+ if ($ip =~ /^\Q$pattern\E/) { $allowed=1; }
+ } else {
+ #some.name.com
+ if (!defined($name)) {
+ use Socket;
+ my $netaddr=inet_aton($ip);
+ ($name)=gethostbyaddr($netaddr,AF_INET);
+ }
+ if ($name =~ /\Q$pattern\E$/i) { $allowed=1; }
+ }
+ if ($allowed) { last; }
+ }
+ return $allowed;
+}
+# JB, 9/24/2002: Any changes in this function may require a change
+# in lonnavmaps::resource::getDateStatus.
sub check_access {
- my ($id) = @_;
- my $date ='';
- my $status = '';
- my $datemsg = '';
- my $lastdate = '';
- my $temp;
- my $type;
- my $passed;
- &Apache::lonxml::debug("checking for part :$id:");
- foreach $temp ("opendate","duedate","answerdate") {
- $lastdate = $date;
- $date = &Apache::lonnet::EXT("resource.$id.$temp");
- &Apache::lonxml::debug("found :$date: for :$temp:");
- if ($date eq '') {
- $date = "an unknown date"; $passed = 0;
- } elsif ($date eq 'con_lost') {
- $date = "an indeterminate date"; $passed = 0;
- } else {
- if (time < $date) { $passed = 0; } else { $passed = 1; }
- $date = localtime $date;
+ my ($id) = @_;
+ my $date ='';
+ my $status;
+ my $datemsg = '';
+ my $lastdate = '';
+ my $temp;
+ my $type;
+ my $passed;
+
+ if ($ENV{'request.state'} eq "construct") {
+ if ($ENV{'form.problemstate'}) {
+ if ($ENV{'form.problemstate'} =~ /^CANNOT_ANSWER/) {
+ if ( ! ($ENV{'form.problemstate'} eq 'CANNOT_ANSWER_correct' &&
+ lc($Apache::lonhomework::problemstatus) eq 'no')) {
+ return ('CANNOT_ANSWER',
+ &mt('is in this state due to author settings.'));
+ }
+ } else {
+ return ($ENV{'form.problemstate'},
+ &mt('is in this state due to author settings.'));
+ }
+ }
+ &Apache::lonxml::debug("in construction ignoring dates");
+ $status='CAN_ANSWER';
+ $datemsg=&mt('is in under construction');
+# return ($status,$datemsg);
+ }
+
+ &Apache::lonxml::debug("checking for part :$id:");
+ &Apache::lonxml::debug("time:".time);
+
+ if ($ENV{'request.state'} ne "construct") {
+ my $allowed=&check_ip_acc(&Apache::lonnet::EXT("resource.$id.acc"));
+ if (!$allowed && ($Apache::lonhomework::browse ne 'F')) {
+ $status='INVALID_ACCESS';
+ $date=&mt("can not be accessed from your location.");
+ return($status,$date);
+ }
+
+ foreach $temp ("opendate","duedate","answerdate") {
+ $lastdate = $date;
+ $date = &Apache::lonnet::EXT("resource.$id.$temp");
+ my $thistype = &Apache::lonnet::EXT("resource.$id.$temp.type");
+ if ($thistype =~ /^(con_lost|no_such_host)/ ||
+ $date =~ /^(con_lost|no_such_host)/) {
+ $status='UNAVAILABLE';
+ $date=&mt("may open later.");
+ return($status,$date);
+ }
+ if ($thistype eq 'date_interval') {
+ if ($temp eq 'opendate') {
+ $date=&Apache::lonnet::EXT("resource.$id.duedate")-$date;
+ }
+ if ($temp eq 'answerdate') {
+ $date=&Apache::lonnet::EXT("resource.$id.duedate")+$date;
+ }
+ }
+ &Apache::lonxml::debug("found :$date: for :$temp:");
+ if ($date eq '') {
+ $date = &mt("an unknown date"); $passed = 0;
+ } elsif ($date eq 'con_lost') {
+ $date = &mt("an indeterminate date"); $passed = 0;
+ } else {
+ if (time < $date) { $passed = 0; } else { $passed = 1; }
+ $date = localtime $date;
+ }
+ if (!$passed) { $type=$temp; last; }
+ }
+ &Apache::lonxml::debug("have :$type:$passed:");
+ if ($passed) {
+ $status='SHOW_ANSWER';
+ $datemsg=$date;
+ } elsif ($type eq 'opendate') {
+ $status='CLOSED';
+ $datemsg = &mt("will open on")." $date";
+ } elsif ($type eq 'duedate') {
+ $status='CAN_ANSWER';
+ $datemsg = &mt("is due at")." $date";
+ } elsif ($type eq 'answerdate') {
+ $status='CLOSED';
+ $datemsg = &mt("was due on")." $lastdate".&mt(", and answers will be available on")." $date";
+ }
+ }
+ if ($status eq 'CAN_ANSWER') {
+ #check #tries, and if correct.
+ my $tries = $Apache::lonhomework::history{"resource.$id.tries"};
+ my $maxtries = &Apache::lonnet::EXT("resource.$id.maxtries");
+ if ( $tries eq '' ) { $tries = '0'; }
+ if ( $maxtries eq '' &&
+ $ENV{'request.state'} ne 'construct') { $maxtries = '2'; }
+ if ($maxtries && $tries >= $maxtries) { $status = 'CANNOT_ANSWER'; }
+ # if (correct and show prob status) or excused then CANNOT_ANSWER
+ if(($Apache::lonhomework::history{"resource.$id.solved"}=~/^correct/
+ &&
+ lc($Apache::lonhomework::problemstatus) ne 'no')
+ ||
+ $Apache::lonhomework::history{"resource.$id.solved"}=~/^excused/) {
+ $status = 'CANNOT_ANSWER';
+ }
+ }
+ if ($status eq 'CAN_ANSWER' || $status eq 'CANNOT_ANSWER') {
+ my $interval=&Apache::lonnet::EXT("resource.$id.interval");
+ &Apache::lonxml::debug("looking for interval $interval");
+ if ($interval) {
+ my $first_access=&Apache::lonnet::get_first_access('map');
+ &Apache::lonxml::debug("looking for accesstime $first_access");
+ if (!$first_access) {
+ $status='NOT_YET_VIEWED';
+ $datemsg=&seconds_to_human_length($interval);
+ } else {
+ my $newdate=localtime($first_access+$interval);
+ if (time > ($first_access+$interval)) {
+ $status='CLOSED';
+ $datemsg = &mt("was due on")." $newdate".&mt(", and answers will be available on")." $date";
+ } else {
+ $datemsg = &mt("is due at")." $newdate";
+ }
+ }
+ }
}
- if (!$passed) { $type=$temp; last; }
- }
- &Apache::lonxml::debug("have :$type:$passed:");
- if ($passed) {
- $status='SHOW_ANSWER';
- $datemsg=$date;
- } elsif ($type eq 'opendate') {
- $status='CLOSED';
- $datemsg = "will open on $date";
- } elsif ($type eq 'duedate') {
- $status='CAN_ANSWER';
- $datemsg = "is due at $date";
- } elsif ($type eq 'answerdate') {
- $status='CLOSED';
- $datemsg = "was due on $lastdate, and answers will be available on $date";
- }
- if ($status eq 'CAN_ANSWER') {
- #check #tries
- my $tries = $Apache::lonhomework::history{"resource.$id.tries"};
- my $maxtries = &Apache::lonnet::EXT("resource.$id.maxtries");
- if ( $tries eq '' ) { $tries = '0'; }
- if ( $maxtries eq '' ) { $maxtries = '2'; }
- if ($tries >= $maxtries) { $status = 'CANNOT_ANSWER'; }
- }
-
- if (($status ne 'CLOSED') && ($Apache::lonhomework::type eq 'exam') &&
- (!$Apache::lonhomework::history{"resource.0.outtoken"})) {
- return ('UNCHECKEDOUT','needs to be checked out');
- }
-
-
- &Apache::lonxml::debug("sending back :$status:$datemsg:");
- if (($Apache::lonhomework::browse eq 'F') && ($status eq 'CLOSED')) {
- &Apache::lonxml::debug("should be allowed to browse a resource when closed");
- $status='CAN_ANSWER';
- $datemsg='is closed but you are allowed to view it';
- }
- if ($ENV{'request.state'} eq "construct") {
- &Apache::lonxml::debug("in construction ignoring dates");
- $status='CAN_ANSWER';
- $datemsg='is in under construction';
- }
- return ($status,$datemsg);
+ #if (($status ne 'CLOSED') && ($Apache::lonhomework::type eq 'exam') &&
+ # (!$Apache::lonhomework::history{"resource.0.outtoken"})) {
+ # return ('UNCHECKEDOUT','needs to be checked out');
+ #}
+
+
+ &Apache::lonxml::debug("sending back :$status:$datemsg:");
+ if (($Apache::lonhomework::browse eq 'F') && ($status eq 'CLOSED')) {
+ &Apache::lonxml::debug("should be allowed to browse a resource when closed");
+ $status='CAN_ANSWER';
+ $datemsg=&mt('is closed but you are allowed to view it');
+ }
+
+ return ($status,$datemsg);
+}
+
+sub seconds_to_human_length {
+ my ($length)=@_;
+
+ my $seconds=$length%60; $length=int($length/60);
+ my $minutes=$length%60; $length=int($length/60);
+ my $hours=$length%24; $length=int($length/24);
+ my $days=$length;
+
+ my $timestr;
+ if ($days > 0) { $timestr.=&mt('[quant,_1,day]',$days); }
+ if ($hours > 0) { $timestr.=($timestr?", ":"").
+ &mt('[quant,_1,hour]',$hours); }
+ if ($minutes > 0) { $timestr.=($timestr?", ":"").
+ &mt('[quant,_1,minute]',$minutes); }
+ if ($seconds > 0) { $timestr.=($timestr?", ":"").
+ &mt('[quant,_1,second]',$seconds); }
+ return $timestr;
}
sub showhash {
- my (%hash) = @_;
- my $resultkey;
- foreach $resultkey (sort keys %hash) {
- &Apache::lonxml::debug("$resultkey ---- $hash{$resultkey}");
- }
- &Apache::lonxml::debug("\n
restored values^\n");
- return '';
+ my (%hash) = @_;
+ &showhashsubset(\%hash,'.');
+ return '';
}
-sub setuppermissions {
- $Apache::lonhomework::browse= &Apache::lonnet::allowed('bre',$ENV{'request.filename'});
- $Apache::lonhomework::viewgrades=&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'});
- return ''
+sub showarray {
+ my ($array)=@_;
+ my $string="(";
+ foreach my $elm (@{ $array }) {
+ if (ref($elm) eq 'ARRAY') {
+ $string.=&showarray($elm);
+ } elsif (ref($elm) eq 'HASH') {
+ $string.= "HASH --- \n
";
+ $string.= &showhashsubset($elm,'.');
+ } else {
+ $string.="$elm,"
+ }
+ }
+ chop($string);
+ $string.=")";
+ return $string;
+}
+
+sub showhashsubset {
+ my ($hash,$keyre) = @_;
+ my $resultkey;
+ foreach $resultkey (sort keys %$hash) {
+ if ($resultkey !~ /$keyre/) { next; }
+ if (ref($$hash{$resultkey}) eq 'ARRAY' ) {
+ &Apache::lonxml::debug("$resultkey ---- ".
+ &showarray($$hash{$resultkey}));
+ } elsif (ref($$hash{$resultkey}) eq 'HASH' ) {
+ &Apache::lonxml::debug("$resultkey ---- $$hash{$resultkey}");
+ &showhashsubset($$hash{$resultkey},'.');
+ } else {
+ &Apache::lonxml::debug("$resultkey ---- $$hash{$resultkey}");
+ }
+ }
+ &Apache::lonxml::debug("\n
restored values^\n");
+ return '';
}
-sub setupheader {
- my $request=$_[0];
- if ($ENV{'browser.mathml'}) {
- $request->content_type('text/xml');
- } else {
- $request->content_type('text/html');
- }
- &Apache::loncommon::no_cache($request);
- $request->send_http_header;
- return OK if $request->header_only;
- return ''
+sub setuppermissions {
+ $Apache::lonhomework::browse= &Apache::lonnet::allowed('bre',$ENV{'request.filename'});
+ my $viewgrades = &Apache::lonnet::allowed('vgr',$ENV{'request.course.id'});
+ if (! $viewgrades &&
+ exists($ENV{'request.course.sec'}) &&
+ $ENV{'request.course.sec'} !~ /^\s*$/) {
+ $viewgrades = &Apache::lonnet::allowed('vgr',$ENV{'request.course.id'}.
+ '/'.$ENV{'request.course.sec'});
+ }
+ $Apache::lonhomework::viewgrades = $viewgrades; # File global variable...dirt.
+ if ($Apache::lonhomework::browse eq 'F' &&
+ $ENV{'form.devalidatecourseresdata'} eq 'on') {
+ my (undef,$courseid) = &Apache::lonxml::whichuser();
+ &Apache::lonnet::devalidatecourseresdata($ENV{"course.$courseid.num"},
+ $ENV{"course.$courseid.domain"});
+ }
+ return ''
}
-sub handle_save_or_undo {
- my ($request,$problem,$result) = @_;
- my $fileout = &Apache::lonnet::filelocation("",$request->uri);
- my $filesave=$fileout.".bak";
-
- if ($ENV{'form.Undo'} eq 'undo') {
- if (copy($filesave,$fileout)) {
- $request->print("Undid changes, Copied $filesave to $fileout
");
+sub setupheader {
+ my $request=$_[0];
+ if ($ENV{'browser.mathml'}) {
+ &Apache::loncommon::content_type($request,'text/xml');
} else {
- $request->print("Unable to undo, unable to copy $filesave to $fileout
");
+ &Apache::loncommon::content_type($request,'text/html');
}
- } else {
- my $fs=Apache::File->new(">$filesave");
- if (defined($fs)) {
- print $fs $$problem;
- $request->print("Making Backup to $filesave
");
- } else {
- $request->print("Unable to make backup $filesave");
+ if (!$Apache::lonxml::debug && ($ENV{'REQUEST_METHOD'} eq 'GET')) {
+ &Apache::loncommon::no_cache($request);
}
- my $fh=Apache::File->new(">$fileout");
- if (defined($fh)) {
- print $fh $$result;
- $request->print("Saving Modifications to $fileout
");
+ $request->set_last_modified(&Apache::lonnet::metadata($request->uri,
+ 'lastrevisiondate'));
+ $request->send_http_header;
+ return OK if $request->header_only;
+ return ''
+}
+
+sub handle_save_or_undo {
+ my ($request,$problem,$result) = @_;
+ my $file = &Apache::lonnet::filelocation("",$request->uri);
+ my $filebak =$file.".bak";
+ my $filetmp =$file.".tmp";
+ my $error=0;
+
+ &Apache::lonnet::correct_line_ends($result);
+
+ if ($ENV{'form.Undo'} eq &mt('undo')) {
+ my $error=0;
+ if (!copy($file,$filetmp)) { $error=1; }
+ if ((!$error) && (!copy($filebak,$file))) { $error=1; }
+ if ((!$error) && (!move($filetmp,$filebak))) { $error=1; }
+ if (!$error) {
+ &Apache::lonxml::info("".&mt("Undid changes, Switched")." $filebak ".&mt("and")." $file
");
+ } else {
+ &Apache::lonxml::info("".&mt("Unable to undo, unable to switch")." $filebak ".&mt("and")." $file
");
+ $error=1;
+ }
} else {
- $request->print("Unable to write to $fileout");
+ my $fs=Apache::File->new(">$filebak");
+ if (defined($fs)) {
+ print $fs $$problem;
+ &Apache::lonxml::info("".&mt("Making Backup to").
+ " $filebak");
+ } else {
+ &Apache::lonxml::info("".&mt("Unable to make backup")." $filebak");
+ $error=2;
+ }
+ my $fh=Apache::File->new(">$file");
+ if (defined($fh)) {
+ print $fh $$result;
+ &Apache::lonxml::info("".&mt("Saving Modifications to").
+ " $file");
+ } else {
+ &Apache::lonxml::info("".
+ &mt("Unable to write to")." $file");
+ $error|=4;
+ }
}
- }
+ return $error;
}
-sub renderpage {
- my ($request,$file) = @_;
-
- my (@targets) = &get_target();
- foreach my $target (@targets) {
- #my $t0 = [&gettimeofday()];
- my $problem=&Apache::lonnet::getfile($file);
- if ($problem == -1) {
- &Apache::lonxml::error(" Unable to find $file");
- $problem='';
+sub analyze_header {
+ my ($request) = @_;
+ my $bodytag='';
+ if ($ENV{'environment.remote'} eq 'off') {
+ $bodytag=&Apache::loncommon::bodytag();
+ }
+ my $result.='
+ '.&mt("Analyzing a problem").'
+ '.$bodytag.&Apache::lonxml::message_location().'
+ ';
+ &Apache::lonxml::add_messages(\$result);
+ $request->print($result);
+ $request->rflush();
+}
+
+sub analyze_footer {
+ my ($request) = @_;
+ my $result='';
+ $request->print($result);
+ $request->rflush();
+}
+
+sub analyze {
+ my ($request,$file) = @_;
+ &Apache::lonxml::debug("Analyze");
+ my $result;
+ my %overall;
+ my %allparts;
+ my $rndseed=$ENV{'form.rndseed'};
+ &analyze_header($request);
+ my %prog_state=
+ &Apache::lonhtmlcommon::Create_PrgWin($request,&mt('Analyze Progress'),
+ &mt('Getting Problem Variants'),
+ $ENV{'form.numtoanalyze'},
+ 'inline',undef);
+ for(my $i=1;$i<$ENV{'form.numtoanalyze'}+1;$i++) {
+ &Apache::lonhtmlcommon::Increment_PrgWin($request,\%prog_state,
+ &mt('last problem'));
+ if (&Apache::loncommon::connection_aborted($request)) { return; }
+ my $subresult=&Apache::lonnet::ssi($request->uri,
+ ('grade_target' => 'analyze'),
+ ('rndseed' => $i+$rndseed));
+ (my $garbage,$subresult)=split(/_HASH_REF__/,$subresult,2);
+ my %analyze=&Apache::lonnet::str2hash($subresult);
+ my @parts;
+ if (defined(@{ $analyze{'parts'} })) {
+ @parts=@{ $analyze{'parts'} };
+ }
+ foreach my $part (@parts) {
+ if (!exists($allparts{$part})) {$allparts{$part}=1;};
+ if ($analyze{$part.'.type'} eq 'numericalresponse' ||
+ $analyze{$part.'.type'} eq 'stringresponse' ||
+ $analyze{$part.'.type'} eq 'formularesponse' ) {
+ push( @{ $overall{$part.'.answer'} },
+ [@{ $analyze{$part.'.answer'} }]);
+ }
+ }
}
-
- my %mystyle;
- my $result = '';
- &Apache::inputtags::initialize_inputtags;
- &Apache::edit::initialize_edit;
- if ($target eq 'web') {
- if (&Apache::lonnet::symbread() eq '') {
- if ($ENV{'request.state'} eq "construct") {
+ &Apache::lonhtmlcommon::Update_PrgWin($request,\%prog_state,
+ &mt('Analyzing Results'));
+ $request->print('
'.&mt('List of possible answers').': ');
+ foreach my $part (sort(keys(%allparts))) {
+ if (defined(@{ $overall{$part.'.answer'} })) {
+ my $num_cols=scalar(@{ $overall{$part.'.answer'}->[0] });
+ $request->print(''.&mt('Part').' '.$part.' |
');
+ my %frequency;
+ foreach my $answer (sort {$a->[0] <=> $b->[0]} (@{ $overall{$part.'.answer'} })) {
+ $frequency{join("\0",@{ $answer })}++;
+ }
+ $request->print(''.&mt('Answer').' | '.&mt('Frequency').' |
');
+ foreach my $answer (sort {(split("\0",$a))[0] <=> (split("\0",$b))[0]} (keys(%frequency))) {
+ $request->print(''.
+ join(' | ',split("\0",$answer)).
+ ' | ('.$frequency{$answer}.
+ ') |
');
+ }
+ $request->print('
');
} else {
- $request->print("Browsing or ambiguous reference, submissions ignored
");
+ $request->print(''.&mt('Response').' '.$part.' '.
+ &mt('is not analyzable at this time').'
');
}
- }
- #if ($Apache::lonhomework::viewgrades eq 'F') {&createmenu('grade',$request); }
}
- if ($target eq 'grade') { &showhash(%Apache::lonhomework::history); }
-
- my $default=&Apache::lonnet::getfile('/home/httpd/html/res/adm/includes/default_homework.lcpm');
- if ($default == -1) {
- &Apache::lonxml::error("Unable to find default_homework.lcpm");
- $default='';
+ if (scalar(keys(%allparts)) == 0 ) {
+ $request->print(''.&mt('Found no analyzable respones in this problem, currently only Numerical, Formula and String response styles are supported.').'
');
}
- $result = &Apache::lonxml::xmlparse($target, $problem,
- $default.&setup_vars($target),%mystyle);
+ &Apache::lonhtmlcommon::Close_PrgWin($request,\%prog_state);
+ &analyze_footer($request);
+ &Apache::lonhomework::showhash(%overall);
+ return $result;
+}
- #$request->print("Result follows:");
- if ($target eq 'modified') {
- &handle_save_or_undo($request,\$problem,\$result);
+sub editxmlmode {
+ my ($request,$file) = @_;
+ my $result;
+ my $problem=&Apache::lonnet::getfile($file);
+ if ($problem eq -1) {
+ &Apache::lonxml::error(" ".&mt('Unable to find').
+ " $file");
+ $problem='';
+ }
+ if (defined($ENV{'form.editxmltext'}) || defined($ENV{'form.Undo'})) {
+ my $error=&handle_save_or_undo($request,\$problem,
+ \$ENV{'form.editxmltext'});
+ if (!$error) { $problem=&Apache::lonnet::getfile($file); }
+ }
+ &Apache::lonhomework::showhashsubset(\%ENV,'^form');
+ if ( $ENV{'form.submit'} eq &mt('Submit Changes and View') ) {
+ &Apache::lonhomework::showhashsubset(\%ENV,'^form');
+ $ENV{'form.problemmode'}='View';
+ &renderpage($request,$file);
} else {
- #my $td=&tv_interval($t0);
- #if ( $Apache::lonxml::debug) {
- #$result =~ s:
';
+ if ($ENV{'environment.remote'} eq 'off') {
+ $bodytag=&Apache::loncommon::bodytag();
+ }
+ $result.=''.$bodytag.&Apache::lonxml::message_location().'
+