--- loncom/homework/lonhomework.pm 2007/04/06 21:21:34 1.266 +++ loncom/homework/lonhomework.pm 2007/12/24 06:35:18 1.287 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Homework handler # -# $Id: lonhomework.pm,v 1.266 2007/04/06 21:21:34 albertel Exp $ +# $Id: lonhomework.pm,v 1.287 2007/12/24 06:35:18 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -49,11 +49,11 @@ use Apache::matchresponse(); use Apache::chemresponse(); use Apache::drawimage(); use Apache::Constants qw(:common); -use HTML::Entities(); use Apache::loncommon(); use Apache::lonlocal; use Time::HiRes qw( gettimeofday tv_interval ); -use Apache::lonnet(); +use HTML::Entities(); +use File::Copy(); # FIXME - improve commenting @@ -63,6 +63,28 @@ BEGIN { } +=pod + +=item set_bubble_lines() + +Called at analysis time to set the bubble lines +hash for the problem.. This should be called in the +end_problemtype tag in analysis mode. + +We fetch the hash of part id counters from lonxml + and push them into analyze:{part_id.bubble_lines}. + +=cut + +sub set_bubble_lines { + my %bubble_counters = &Apache::lonxml::get_bubble_line_hash(); + + foreach my $key (keys(%bubble_counters)) { + $Apache::lonhomework::analyze{"$key.bubble_lines"} = + $bubble_counters{"$key"}; + } +} + # # Decides what targets to render for. # Implicit inputs: @@ -112,7 +134,10 @@ sub get_target { return ('web'); } } else { - if ( $env{'form.problemmode'} eq &mt('View') || + if ($env{'form.problemstate'} eq 'WEB_GRADE') { + #$env{'form.webgrade'} = 'yes'; + return ('grade','webgrade','answer'); + } elsif ( $env{'form.problemmode'} eq &mt('View') || $env{'form.problemmode'} eq &mt('Discard Edits and View')) { if ( defined($env{'form.submitted'}) && (!defined($env{'form.resetdata'})) && @@ -124,7 +149,7 @@ sub get_target { } 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') ) { + if ( $env{'form.submit'} eq &mt('Save and View') ) { return ('modified','web','answer'); } else { return ('modified','no_output_web','edit'); @@ -185,7 +210,6 @@ sub proctor_checked_in { return 0; } -$Apache::lonxml::browse=''; sub check_ip_acc { my ($acc)=@_; &Apache::lonxml::debug("acc is $acc"); @@ -193,7 +217,8 @@ sub check_ip_acc { return 1; } my $allowed=0; - my $ip=$ENV{'REMOTE_ADDR'}; + my $ip=$env{'request.host'} || $ENV{'REMOTE_ADDR'}; + my $name; foreach my $pattern (split(',',$acc)) { $pattern =~ s/^\s*//; @@ -373,8 +398,8 @@ sub check_access { 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')) { + if ( ! ($env{'form.problemstate'} eq 'CANNOT_ANSWER_correct' + && &hide_problem_status())) { return ('CANNOT_ANSWER', &mt('is in this state due to author settings.')); } @@ -433,7 +458,7 @@ sub check_access { $date = &mt("an indeterminate date"); $passed = 0; } else { if (time < $date) { $passed = 0; } else { $passed = 1; } - $date = localtime $date; + $date = &Apache::lonlocal::locallocaltime($date); } if (!$passed) { $type=$temp; last; } } @@ -464,24 +489,28 @@ sub check_access { # 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') + &show_problem_status()) || $Apache::lonhomework::history{"resource.$id.solved"}=~/^excused/) { $status = 'CANNOT_ANSWER'; } + if ($status eq 'CANNOT_ANSWER' + && &show_answer_problem_status()) { + $status = 'SHOW_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'); + my @interval=&Apache::lonnet::EXT("resource.$id.interval"); + &Apache::lonxml::debug("looking for interval @interval"); + if ($interval[0]) { + my $first_access=&Apache::lonnet::get_first_access($interval[1]); &Apache::lonxml::debug("looking for accesstime $first_access"); if (!$first_access) { $status='NOT_YET_VIEWED'; my $due_date = &due_date($id); my $seconds_left = $due_date - time; - if ($seconds_left > $interval || $due_date eq '') { - $seconds_left = $interval; + if ($seconds_left > $interval[0] || $due_date eq '') { + $seconds_left = $interval[0]; } $datemsg=&seconds_to_human_length($seconds_left); } @@ -507,18 +536,19 @@ sub check_access { sub due_date { my ($part_id,$symb,$udom,$uname)=@_; my $date; - my $interval= &Apache::lonnet::EXT("resource.$part_id.interval",$symb, + my @interval= &Apache::lonnet::EXT("resource.$part_id.interval",$symb, $udom,$uname); - &Apache::lonxml::debug("looking for interval $part_id $symb $interval"); + &Apache::lonxml::debug("looking for interval $part_id $symb @interval"); my $due_date= &Apache::lonnet::EXT("resource.$part_id.duedate",$symb, $udom,$uname); &Apache::lonxml::debug("looking for due_date $part_id $symb $due_date"); - if ($interval =~ /\d+/) { - my $first_access=&Apache::lonnet::get_first_access('map',$symb); - &Apache::lonxml::debug("looking for first_access $first_access"); + if ($interval[0] =~ /\d+/) { + my $first_access=&Apache::lonnet::get_first_access($interval[1],$symb); + &Apache::lonxml::debug("looking for first_access $first_access ($interval[1])"); if (defined($first_access)) { - $interval = $first_access+$interval; - $date = ($interval < $due_date)? $interval : $due_date; + my $interval = $first_access+$interval[0]; + $date = (!$due_date || $interval < $due_date) ? $interval + : $due_date; } else { $date = $due_date; } @@ -658,9 +688,9 @@ sub handle_save_or_undo { my $error=0; 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 (!&File::Copy::copy($file,$filetmp)) { $error=1; } + if ((!$error) && (!&File::Copy::copy($filebak,$file))) { $error=1; } + if ((!$error) && (!&File::Copy::move($filetmp,$filebak))) { $error=1; } if (!$error) { &Apache::lonxml::info("

". &mt("Undid changes, Switched [_1] and [_2]", @@ -721,11 +751,14 @@ sub analyze_header {

'. &Apache::structuretags::remember_problem_state().' +
-
+
+ -
+
+
'; &Apache::lonxml::add_messages(\$result); $request->print($result); @@ -785,12 +818,20 @@ sub analyze { $i++; } } + if (!keys(%{ $analyze{$part.'.answer'} })) { + my $answer_part = + [''.&mt('Error').'']; + $seedexample{join("\0",$part,0,@{$answer_part})}= + $thisseed; + push( @{ $overall{$part.'.answer'}[0] }, + $answer_part); + } } } } &Apache::lonhtmlcommon::Update_PrgWin($request,\%prog_state, &mt('Analyzing Results')); - $request->print('
'.&mt('List of possible answers').': '); + $request->print('
'.&mt('List of possible answers').': '); foreach my $part (sort(keys(%allparts))) { if (defined(@{ $overall{$part.'.answer'} })) { for (my $i=0;$i 80) { $cols = 80; } if ($cols < 70) { $cols = 70; } if ($rows < 20) { $rows = 20; } + my $js = + &Apache::edit::js_change_detection(). + &Apache::loncommon::resize_textarea_js(); + my $only_body = ($env{'environment.remote'} eq 'off')? 0 : 1; my $start_page = - &Apache::loncommon::start_page(&mt("EditXML [_1]",$file), - &Apache::edit::js_change_detection(), - {'no_auto_mt_title' => 1,}); + &Apache::loncommon::start_page(&mt("EditXML [_1]",$file),$js, + {'no_auto_mt_title' => 1, + 'only_body' => $only_body, + 'add_entries' => { + 'onresize' => q[resize_textarea('LC_editxmltext','LC_aftertextarea')], + 'onload' => q[resize_textarea('LC_editxmltext','LC_aftertextarea')], + }}); $result.=$start_page. &renderpage($request,$file,['no_output_web'],1). - &Apache::lonxml::message_location().' -
'. &Apache::structuretags::remember_problem_state().' - - - - -
- - -
- ' . $xml_help . ' -
- - +
+ +
+ '.&mt('Problem Editing').&Apache::loncommon::help_open_topic('Problem_Editor_XML_Index').' + + '.&Apache::loncommon::helpLatexCheatsheet().' +
+
+ + + + +
+
+ + +
+
+ '.&Apache::lonxml::message_location().' +
+ ' . ' + +
+
'.&Apache::loncommon::end_page(); &Apache::lonxml::add_messages(\$result); $request->print($result); @@ -898,6 +995,7 @@ sub renderpage { my @targets = @{$targets || [&get_target()]}; &Apache::lonhomework::showhashsubset(\%env,'form.'); &Apache::lonxml::debug("Running targets ".join(':',@targets)); + my $overall_result; foreach my $target (@targets) { # FIXME need to do something intelligent when a problem goes @@ -935,7 +1033,7 @@ sub renderpage { &Apache::lonxml::debug("Should be parsing now"); $result .= &Apache::lonxml::xmlparse($request, $target, $problem, &setup_vars($target),%mystyle); - undef($Apache::lonhomework::parsing_a_problem); + &finished_parsing(); if (!$output) { $result = ''; } #$request->print("Result follows:"); if ($target eq 'modified') { @@ -966,50 +1064,76 @@ sub renderpage { } } -# with no arg it returns a HTML

".&mt("To create a new $extension, select a template from the". - "pull-down menu below. Then click on the \"Create $extension\" button.")." + " list below. Then click on the \"Create $extension\" button.")."

"); if (defined($templatelist)) { - $request->print(""); + $request->print($templatelist); } - $request->print("
"); + $request->print('
'); $request->print("

".&Apache::loncommon::end_page()); } - return ''; + return; } +sub update_construct_style { + if ($env{'request.state'} eq "construct" + && $env{'form.problemmode'} eq &mt('View') + && defined($env{'form.submitted'}) + && !defined($env{'form.resetdata'}) + && !defined($env{'form.newrandomization'})) { + if ((!$env{'form.style_file'} && $env{'construct.style'}) + ||$env{'form.clear_style_file'}) { + &Apache::lonnet::delenv('construct\\.style'); + } elsif ($env{'form.style_file'} + && $env{'construct.style'} ne $env{'form.style_file'}) { + &Apache::lonnet::appenv('construct.style' => + $env{'form.style_file'}); + } + } +} + + sub handler { #my $t0 = [&gettimeofday()]; my $request=$_[0]; @@ -1094,6 +1234,7 @@ sub handler { } elsif ($env{'form.problemmode'} eq &mt('Calculate answers')) { &analyze($request,$file); } else { + &update_construct_style(); &renderpage($request,$file); } } else {