--- loncom/homework/lonhomework.pm 2016/05/13 22:48:09 1.361 +++ loncom/homework/lonhomework.pm 2017/04/03 13:01:43 1.368 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Homework handler # -# $Id: lonhomework.pm,v 1.361 2016/05/13 22:48:09 raeburn Exp $ +# $Id: lonhomework.pm,v 1.368 2017/04/03 13:01:43 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -210,7 +210,7 @@ sub proctor_checked_in { } sub check_slot_access { - my ($id,$type,$symb)=@_; + my ($id,$type,$symb,$partlist)=@_; # does it pass normal muster my ($status,$datemsg)=&check_access($id,$symb); @@ -228,13 +228,15 @@ sub check_slot_access { $checkin = "resource.$version.0.checkedin"; } my $checkedin = $Apache::lonhomework::history{$checkin}; - my ($returned_slot,$slot_name,$checkinslot,$ipused,$blockip,$now,$ip); + my ($returned_slot,$slot_name,$checkinslot,$ipused,$blockip,$now,$ip, + $consumed_uniq); $now = time; - $ip=$env{'request.host'} || $ENV{'REMOTE_ADDR'}; + $ip=$ENV{'REMOTE_ADDR'} || $env{'request.host'}; if ($checkedin) { $checkinslot = $Apache::lonhomework::history{"$checkin.slot"}; my %slot=&Apache::lonnet::get_slot($checkinslot); + $consumed_uniq = $slot{'uniqueperiod'}; if ($slot{'iptied'}) { $ipused = $Apache::lonhomework::history{"$checkin.ip"}; unless (($ip ne '') && ($ipused eq $ip)) { @@ -349,9 +351,48 @@ sub check_slot_access { ($Apache::lonhomework::history{"resource.$version.0.status"} eq 'pass' || $Apache::lonhomework::history{"resource.0.solved"} =~ /^correct_/ ); } elsif ($type eq 'problem') { - $got_grade = 1; - $is_correct = - ($Apache::lonhomework::history{"resource.0.solved"} =~/^correct_/); + if ((ref($partlist) eq 'ARRAY') && (@{$partlist} > 0)) { + my ($numcorrect,$numgraded) = (0,0); + foreach my $part (@{$partlist}) { + my $currtries = $Apache::lonhomework::history{"resource.$part.tries"}; + my $maxtries = &Apache::lonnet::EXT("resource.$part.maxtries",$symb); + my $probstatus = &Apache::structuretags::get_problem_status($part); + my $earlyout; + unless (($probstatus eq 'no') || + ($probstatus eq 'no_feedback_ever')) { + if ($Apache::lonhomework::history{"resource.$part.solved"} =~/^correct_/) { + $numcorrect ++; + } else { + $earlyout = 1; + } + } + if (($currtries == $maxtries) || ($is_correct)) { + $earlyout = 1; + } else { + $numgraded ++; + } + last if ($earlyout); + } + my $numparts = scalar(@{$partlist}); + if ($numparts == $numcorrect) { + $is_correct = 1; + } + if ($numparts == $numgraded) { + $got_grade = 1; + } + } else { + my $currtries = $Apache::lonhomework::history{"resource.0.tries"}; + my $maxtries = &Apache::lonnet::EXT("resource.0.maxtries",$symb); + my $probstatus = &Apache::structuretags::get_problem_status('0'); + unless (($probstatus eq 'no') || + ($probstatus eq 'no_feedback_ever')) { + $is_correct = + ($Apache::lonhomework::history{"resource.0.solved"} =~/^correct_/); + } + unless (($currtries == $maxtries) || ($is_correct)) { + $got_grade = 1; + } + } } &Apache::lonxml::debug(" slot is $slotstatus checkedin ($checkedin) got_grade ($got_grade) is_correct ($is_correct)"); @@ -384,15 +425,57 @@ sub check_slot_access { &Apache::loncommon::get_future_slots($cnum,$cdom,$now,$symb); if ((ref($reservable_now_order) eq 'ARRAY') && (ref($reservable_now) eq 'HASH')) { if (@{$reservable_now_order} > 0) { - $slotstatus = 'RESERVABLE'; - $datemsg = $reservable_now->{$reservable_now_order->[-1]}{'endreserve'}; + if ((!$checkedin) || (ref($consumed_uniq) ne 'ARRAY')) { + $slotstatus = 'RESERVABLE'; + $datemsg = $reservable_now->{$reservable_now_order->[-1]}{'endreserve'}; + } else { + my ($uniqstart,$uniqend,$useslot); + if (ref($consumed_uniq) eq 'ARRAY') { + ($uniqstart,$uniqend)=@{$consumed_uniq}; + } + foreach my $slot (reverse(@{$reservable_now_order})) { + if ($reservable_now->{$slot}{'uniqueperiod'} =~ /^(\d+)\,(\d+)$/) { + my ($new_uniq_start,$new_uniq_end) = ($1,$2); + next if (! + ($uniqstart < $new_uniq_start && $uniqend < $new_uniq_start) || + ($uniqstart > $new_uniq_end && $uniqend > $new_uniq_end )); + } + $useslot = $slot; + last; + } + if ($useslot) { + $slotstatus = 'RESERVABLE'; + $datemsg = $reservable_now->{$useslot}{'endreserve'}; + } + } } } unless ($slotstatus eq 'RESERVABLE') { if ((ref($reservable_future_order) eq 'ARRAY') && (ref($reservable_future) eq 'HASH')) { if (@{$reservable_future_order} > 0) { - $slotstatus = 'RESERVABLE_LATER'; - $datemsg = $reservable_future->{$reservable_future_order->[0]}{'startreserve'}; + if ((!$checkedin) || (ref($consumed_uniq) ne 'ARRAY')) { + $slotstatus = 'RESERVABLE_LATER'; + $datemsg = $reservable_future->{$reservable_future_order->[0]}{'startreserve'}; + } else { + my ($uniqstart,$uniqend,$useslot); + if (ref($consumed_uniq) eq 'ARRAY') { + ($uniqstart,$uniqend)=@{$consumed_uniq}; + } + foreach my $slot (@{$reservable_future_order}) { + if ($reservable_future->{$slot}{'uniqueperiod'} =~ /^(\d+),(\d+)$/) { + my ($new_uniq_start,$new_uniq_end) = ($1,$2); + next if (! + ($uniqstart < $new_uniq_start && $uniqend < $new_uniq_start) || + ($uniqstart > $new_uniq_end && $uniqend > $new_uniq_end )); + } + $useslot = $slot; + last; + } + if ($useslot) { + $slotstatus = 'RESERVABLE_LATER'; + $datemsg = $reservable_future->{$useslot}{'startreserve'}; + } + } } } } @@ -561,15 +644,16 @@ sub check_access { if ($status eq 'CAN_ANSWER' || $status eq 'CANNOT_ANSWER') { my @interval=&Apache::lonnet::EXT("resource.$id.interval",$symb); &Apache::lonxml::debug("looking for interval @interval"); - if ($interval[0]) { + if ($interval[0]=~ /^\d+/) { my $first_access=&Apache::lonnet::get_first_access($interval[1],$symb); &Apache::lonxml::debug("looking for accesstime $first_access"); if (!$first_access) { $status='NOT_YET_VIEWED'; my $due_date = &due_date($id,$symb); my $seconds_left = $due_date - time; - if ($seconds_left > $interval[0] || $due_date eq '') { - $seconds_left = $interval[0]; + my ($timelimit) = ($interval[0] =~ /^(\d+)/); + if ($seconds_left > $timelimit || $due_date eq '') { + $seconds_left = $timelimit; } $datemsg=&seconds_to_human_length($seconds_left); } @@ -604,7 +688,8 @@ sub due_date { 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)) { - my $interval = $first_access+$interval[0]; + my ($timelimit) = ($interval[0] =~ /^(\d+)/); + my $interval = $first_access+$timelimit; $date = (!$due_date || $interval < $due_date) ? $interval : $due_date; } else { @@ -1346,18 +1431,39 @@ sub get_template_html { sub newproblem { my ($request) = @_; - if ($env{'form.mode'} eq 'blank'){ + if ($env{'form.mode'} eq 'blank'){ my $dest = &Apache::lonnet::filelocation("",$request->uri); - &File::Copy::copy('/home/httpd/html/res/adm/includes/templates/blank.problem',$dest); + my $templatefilename = + $request->dir_config('lonIncludes').'/templates/blank.problem'; + &File::Copy::copy($templatefilename,$dest); &renderpage($request,$dest); return; } + my $errormsg; if ($env{'form.template'}) { - my $file = $env{'form.template'}; - my $dest = &Apache::lonnet::filelocation("",$request->uri); - &File::Copy::copy($file,$dest); - &renderpage($request,$dest); - return; + my $file; + my ($extension) = ($env{'form.template'} =~ /\.(\w+)$/); + if ($extension) { + my @files = &get_template_list($extension); + foreach my $poss (@files) { + if (ref($poss) eq 'ARRAY') { + if ($env{'form.template'} eq $poss->[0]) { + $file = $env{'form.template'}; + last; + } + } + } + if ($file) { + my $dest = &Apache::lonnet::filelocation("",$request->uri); + &File::Copy::copy($file,$dest); + &renderpage($request,$dest); + return; + } else { + $errormsg = '
'.&mt('Invalid template file.').'
'; + } + } else { + $errormsg = ''.&mt('Invalid template file; template needs to be a .problem, .library, or .task file.').'
'; + } } my ($extension) = ($request->uri =~ m/\.(\w+)$/); @@ -1374,7 +1480,6 @@ sub newproblem { } else { my $url=&HTML::Entities::encode($request->uri,'<>&"'); my $dest = &Apache::lonnet::filelocation("",$request->uri); - my $errormsg; my $instructions; my $brcrum = [{'href' => &Apache::loncommon::authorspace($request->uri), 'text' => 'Authoring Space'}, @@ -1702,16 +1807,15 @@ sub default_xml_tag { sub helpmenu_datastructure { - my $width = 500; - my $height = 600; - + # filename, title, width, height my $helpers = [ - ['Problem_LON-CAPA_Functions', &mt('Script Functions')], - ['Greek_Symbols', &mt('Greek Symbols')], - ['Other_Symbols', &mt('Other Symbols')], - ['Authoring_Output_Tags', &mt('Output Tags')], - ['Authoring_Multilingual_Problems', - &mt('How to create problems in different languages')] + ['Problem_LON-CAPA_Functions.hlp', &mt('Script Functions'), 800, 600], + ['Greek_Symbols.hlp', &mt('Greek Symbols'), 500, 600], + ['Other_Symbols.hlp', &mt('Other Symbols'), 500, 600], + ['Authoring_Output_Tags.hlp', &mt('Output Tags'), 800, 600], + ['Authoring_Multilingual_Problems.hlp', + &mt('How to create problems in different languages'), 800, 600], + ['loncapa.html', &mt('Language reference'), 800, 600], ]; my $help_structure = []; @@ -1719,7 +1823,15 @@ sub helpmenu_datastructure { foreach my $count (0..(scalar(@{$helpers})-1)) { my $filename = $helpers->[$count]->[0]; my $title = $helpers->[$count]->[1]; - my $href = &HTML::Entities::encode("javascript:openMyModal('/adm/help/$filename.hlp',$width,$height,'yes');"); + my $width = $helpers->[$count]->[2]; + my $height = $helpers->[$count]->[3]; + if ($width eq '') { + $width = 500; + } + if ($height eq '') { + $height = 600; + } + my $href = &HTML::Entities::encode("javascript:openMyModal('/adm/help/$filename',$width,$height,'yes');"); push @{$help_structure}, [$href, $title, undef]; }