';
+ my ($mode)=@_;
+ my $return = ''.
+ &remember_problem_state('edit').'
+ ' . &Apache::lonxml::message_location();
+ $return .= '
+ ';
+
+ $return .= '
+
+ ';
+ return $return;
}
+
sub problem_edit_footer {
+ my $resource = $env{'request.ambiguous'};
return ' |
'.
-
- &Apache::lonhtmlcommon::htmlareaselectactive(&Apache::lonhtmlcommon::get_htmlareafields()).
"\n\n".&Apache::loncommon::end_page();
}
@@ -472,6 +936,7 @@ sub problem_web_to_edit_header {
".&option('anonsurvey' ,'problemtype').&mt("Anonymous Survey Question")."
".&option('anonsurveycred' ,'problemtype').&mt("Anonymous Survey Question (with credit)")."
".&option('practice' ,'problemtype').&mt("Practice Problem")."
+ ".&option('randomizetry' ,'problemtype').&mt("New Randomization Each Try")."
$show_all
@@ -482,7 +947,7 @@ $show_all
@@ -522,7 +987,7 @@ $show_all
- ';
@@ -584,7 +1049,7 @@ sub initialize_storage {
}
%Apache::lonhomework::history=
&Apache::lonnet::tmprestore($namespace,'',$domain,$name);
- my ($temp)=keys %Apache::lonhomework::history ;
+ my ($temp)=keys(%Apache::lonhomework::history);
&Apache::lonxml::debug("Return message of $temp");
} else {
%Apache::lonhomework::history=
@@ -592,7 +1057,7 @@ sub initialize_storage {
}
#ignore error conditions
- my ($temp)=keys %Apache::lonhomework::history ;
+ my ($temp)=keys(%Apache::lonhomework::history);
if ($temp =~ m/^error:.*/) { %Apache::lonhomework::history=(); }
}
@@ -600,12 +1065,37 @@ sub initialize_storage {
=item finalize_storage()
- Stores away the result has to a student's environment
- checks form.grade_ for specific values, other wises stores
- to the running users environment
- Will increment totals for attempts, students, and corrects
- if running user has student role.
-
+ Stores away the result hash to a student's environment;
+ checks form.grade_ for specific values, otherwise stores
+ to the running user's environment.
+
+ &check_correctness_changes() is called in two circumstances
+ in which the results hash is to be stored permanently, for
+ grading triggered by a student's submission, where feedback on
+ correctness is to be provided to the student.
+
+ 1. Immediately prior to storing the results hash
+
+ To handle the case where a student's submission (and award) were
+ stored after history was retrieved in &initialize_storage(), e.g.,
+ if a student submitted answers in quick succession (e.g., from
+ multiple tabs). &Apache::inputtags::hidealldata() is called for
+ any parts with out-of-order storage (i.e., correct then incorrect,
+ where awarded >= 1 when correct).
+
+ 2. Immediately after storing the results hash
+
+ To handle the case where lond on the student's homeserver returns
+ delay:N -- where N is the number of transactions between the last
+ retrieved in &initialize_storage() and the last stored immediately
+ before permanent storage of the current transaction via
+ lond::store_handler(). &Apache::grades::makehidden() is called
+ for any parts with out-of-order storage (i.e., correct then incorrect,
+ where awarded >= 1 when correct).
+
+ Will call &store_aggregates() to increment totals for attempts,
+ students, and corrects, if running user has student role.
+
=cut
@@ -617,6 +1107,8 @@ sub finalize_storage {
delete(@Apache::lonhomework::results{@remove});
my ($symb,$courseid,$domain,$name) =
&Apache::lonnet::whichuser($given_symb);
+ my ($passback,$pbscope,$pbmap,$pbsymb,$pbtype,$crsdef,$ltinum,
+ $ltiref,$total,$possible,$dopassback);
if ($env{'request.state'} eq 'construct'
|| $symb eq ''
|| $Apache::lonhomework::type eq 'practice') {
@@ -626,10 +1118,195 @@ sub finalize_storage {
$namespace,'',$domain,$name);
&Apache::lonxml::debug('Construct Store return message:'.$result);
} else {
+ my ($laststore,$checkedparts,@parts,%postcorrect,%record);
+ if (($env{'user.name'} eq $name) && ($env{'user.domain'} eq $domain) &&
+ (!$Apache::lonhomework::scantronmode) && (!defined($env{'form.grade_symb'})) &&
+ (!defined($env{'form.grade_courseid'}))) {
+ if (($env{'request.lti.login'}) || ($env{'request.deeplink.login'})) {
+ my ($map)=&Apache::lonnet::decode_symb($symb);
+ $map = &Apache::lonnet::clutter($map);
+ if ($env{'request.lti.login'}) {
+ ($passback,$pbscope,$pbmap,$pbsymb,$ltinum,$ltiref) =
+ &needs_lti_passback($courseid,$symb,$map);
+ } elsif ($env{'request.deeplink.login'}) {
+ ($passback,$pbscope,$pbmap,$pbsymb,$crsdef,$ltinum,$ltiref) =
+ &needs_linkprot_passback($courseid,$symb,$map);
+ }
+ }
+ if ($Apache::lonhomework::history{'version'}) {
+ $laststore = $Apache::lonhomework::history{'version'}.'='.
+ $Apache::lonhomework::history{'timestamp'};
+ } else {
+ $laststore = '0=0';
+ }
+ %record = &Apache::lonnet::restore($symb,$courseid,$domain,$name);
+ if ($record{'version'}) {
+ my ($newversion,$oldversion,$oldtimestamp);
+ if ($Apache::lonhomework::history{'version'}) {
+ $oldversion = $Apache::lonhomework::history{'version'};
+ $oldtimestamp = $Apache::lonhomework::history{'timestamp'};
+ } else {
+ $oldversion = 0;
+ $oldtimestamp = 0;
+ }
+ if ($record{'version'} > $oldversion) {
+ if ($record{'timestamp'} >= $oldtimestamp) {
+ $laststore = $record{'version'}.'='.$record{'timestamp'};
+ $newversion = $record{'version'} + 1;
+ $checkedparts = 1;
+ foreach my $key (keys(%Apache::lonhomework::results)) {
+ if ($key =~ /^resource\.([^\.]+)\.solved$/) {
+ my $part = $1;
+ if ($Apache::lonhomework::results{$key} eq 'incorrect_attempted') {
+ push(@parts,$part);
+ }
+ }
+ }
+ if (@parts) {
+ my @parts_to_hide = &check_correctness_changes($symb,$courseid,$domain,$name,
+ \%record,\@parts,$newversion,
+ $oldversion);
+ if (@parts_to_hide) {
+ foreach my $part (@parts_to_hide) {
+ $postcorrect{$part} = 1;
+ &Apache::inputtags::hidealldata($part);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
$result=&Apache::lonnet::cstore(\%Apache::lonhomework::results,
- $symb,$courseid,$domain,$name);
+ $symb,$courseid,$domain,$name,$laststore);
+ if ($result =~ /^delay\:(\d+)$/) {
+ my $numtrans = $1;
+ my ($oldversion) = split(/=/,$laststore);
+ if ($numtrans) {
+ my $newversion = $oldversion + 1 + $numtrans;
+ my @possparts;
+ if ($checkedparts) {
+ foreach my $part (@parts) {
+ unless ($postcorrect{$part}) {
+ push(@possparts,$part);
+ }
+ }
+ } else {
+ foreach my $key (keys(%Apache::lonhomework::results)) {
+ if ($key =~ /^resource\.([^\.]+)\.solved$/) {
+ my $part = $1;
+ unless ($postcorrect{$part}) {
+ if ($Apache::lonhomework::results{$key} eq 'incorrect_attempted') {
+ push(@possparts,$part);
+ }
+ }
+ }
+ }
+ }
+ if (@possparts) {
+ my %newrecord = &Apache::lonnet::restore($symb,$courseid,$domain,$name);
+ my @parts_to_hide = &check_correctness_changes($symb,$courseid,$domain,$name,
+ \%newrecord,\@possparts,$newversion,
+ $oldversion);
+ if (@parts_to_hide) {
+ my $partslist = join(',',@parts_to_hide);
+ &Apache::grades::makehidden($newversion,$partslist,\%newrecord,$symb,$domain,$name,1);
+ }
+ }
+ }
+ }
+ if ($passback) {
+ foreach my $key (keys(%Apache::lonhomework::results)) {
+ if ($key =~ /^resource\.([^\.]+)\.solved$/) {
+ my $part = $1;
+ if ((($Apache::lonhomework::results{$key} =~ /^correct_/) ||
+ ($Apache::lonhomework::results{$key} eq 'incorrect_attempted')) &&
+ ($Apache::lonhomework::results{"resource.$part.tries"})) {
+ $dopassback = 1;
+ last;
+ }
+ }
+ }
+ }
+ if (($dopassback) && ($pbscope eq 'resource') && ($pbsymb eq $symb)) {
+ $total = 0;
+ $possible = 0;
+ my $navmap = Apache::lonnavmaps::navmap->new();
+ if (ref($navmap)) {
+ my $res = $navmap->getBySymb($symb);
+ if (ref($res)) {
+ my $partlist = $res->parts();
+ if (ref($partlist) eq 'ARRAY') {
+ foreach my $part (@{$partlist}) {
+ unless (exists($Apache::lonhomework::results{"resource.$part.solved"})) {
+ next if ($Apache::lonhomework::record{"resource.$part.solved"} =~/^excused/);
+ my $weight = &Apache::lonnet::EXT("resource.$part.weight",$symb);
+ $possible += $weight;
+ if (($record{'version'}) && (exists($record{"resource.$part.awarded"}))) {
+ my $awarded = $record{"resource.$part.awarded"};
+ if ($awarded) {
+ $total += $weight * $awarded;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ foreach my $key (keys(%Apache::lonhomework::results)) {
+ if ($key =~ /^resource\.([^\.]+)\.awarded$/) {
+ my $part = $1;
+ my $weight = &Apache::lonnet::EXT("resource.$part.weight",$symb);
+ $possible += $weight;
+ my $awarded = $Apache::lonhomework::results{$key};
+ if ($awarded) {
+ $total += $weight * $awarded;
+ }
+ }
+ }
+ }
&Apache::lonxml::debug('Store return message:'.$result);
&store_aggregates($symb,$courseid);
+ if ($dopassback) {
+ my $scoreformat = 'decimal';
+ if (($env{'request.lti.login'}) || ($env{'request.deeplink.login'})) {
+ if (ref($ltiref) eq 'HASH') {
+ if ($ltiref->{'scoreformat'} =~ /^(decimal|ratio|percentage)$/) {
+ $scoreformat = $1;
+ }
+ }
+ }
+ my ($pbid,$pburl,$pbtype);
+ if ($env{'request.lti.login'}) {
+ $pbid = $env{'request.lti.passbackid'};
+ $pburl = $env{'request.lti.passbackurl'};
+ $pbtype = 'lti';
+ } elsif ($env{'request.deeplink.login'}) {
+ $pbid = $env{'request.linkprotpbid'};
+ $pburl = $env{'request.linkprotpburl'};
+ $pbtype = 'linkprot';
+ }
+ my $ltigrade = {
+ 'ltinum' => $ltinum,
+ 'lti' => $ltiref,
+ 'crsdef' => $crsdef,
+ 'cid' => $courseid,
+ 'uname' => $env{'user.name'},
+ 'udom' => $env{'user.domain'},
+ 'pbid' => $pbid,
+ 'pburl' => $pburl,
+ 'pbtype' => $pbtype,
+ 'scope' => $pbscope,
+ 'pbmap' => $pbmap,
+ 'pbsymb' => $pbsymb,
+ 'format' => $scoreformat,
+ };
+ if ($pbscope eq 'resource') {
+ $ltigrade->{'total'} = $total;
+ $ltigrade->{'possible'} = $possible;
+ }
+ push(@Apache::lonhomework::ltipassback,$ltigrade);
+ }
}
} else {
&Apache::lonxml::debug('Nothing to store');
@@ -637,6 +1314,150 @@ sub finalize_storage {
return $result;
}
+sub needs_lti_passback {
+ my ($courseid,$symb,$map) = @_;
+ if (($env{'request.lti.passbackid'}) && ($env{'request.lti.passbackurl'})) {
+ if ($courseid =~ /^($LONCAPA::match_domain)_($LONCAPA::match_courseid)$/) {
+ my ($cdom,$cnum) = ($1,$2);
+ my %lti = &Apache::lonnet::get_domain_lti($cdom,'provider');
+ if (ref($lti{$env{'request.lti.login'}}) eq 'HASH') {
+ if ($lti{$env{'request.lti.login'}}{'passback'}) {
+ my $itemnum = $env{'request.lti.login'};
+ my ($ltiscope,$ltiuri,$ltisymb) =
+ &LONCAPA::ltiutils::lti_provider_scope($env{'request.lti.uri'},
+ $cdom,$cnum,1);
+ my ($passback,$ltimap);
+ if ($ltiscope eq 'resource') {
+ if ($ltisymb eq $symb) {
+ $passback = 1;
+ }
+ } elsif ($ltiscope eq 'map') {
+ if ($ltiuri eq $map) {
+ $passback = 1;
+ $ltimap = $map;
+ }
+ } elsif ($ltiscope eq 'course') {
+ if (($env{'request.lti.uri'} eq "/$cdom/$cnum") || ($env{'request.lti.uri'} eq '')) {
+ $passback = 1;
+ }
+ }
+ return ($passback,$ltiscope,$ltimap,$ltisymb,$itemnum,$lti{$itemnum});
+ }
+ }
+ }
+ }
+ return;
+}
+
+sub needs_linkprot_passback {
+ my ($courseid,$symb,$map) = @_;
+ if (($env{'request.linkprotpbid'}) && ($env{'request.linkprotpburl'})) {
+ if ($courseid =~ /^($LONCAPA::match_domain)_($LONCAPA::match_courseid)$/) {
+ my ($cdom,$cnum) = ($1,$2);
+ my ($deeplink_symb,$deeplink_map,$deeplink,$passback);
+ $deeplink_symb = &Apache::loncommon::deeplink_login_symb($cnum,$cdom);
+ if ($deeplink_symb) {
+ if ($deeplink_symb =~ /\.(page|sequence)$/) {
+ $deeplink_map = &Apache::lonnet::deversion((&Apache::lonnet::decode_symb($deeplink_symb))[2]);
+ my $navmap = Apache::lonnavmaps::navmap->new();
+ if (ref($navmap)) {
+ $deeplink = $navmap->get_mapparam(undef,$deeplink_map,'0.deeplink');
+ }
+ } else {
+ $deeplink = &Apache::lonnet::EXT('resource.0.deeplink',$deeplink_symb);
+ $deeplink_map = &Apache::lonnet::deversion((&Apache::lonnet::decode_symb($deeplink_symb))[0]);
+ }
+ if (($deeplink ne '') && ($env{'request.linkprot'} ne '')) {
+ my ($itemid,$tinyurl) = split(/:/,$env{'request.linkprot'});
+ if ($itemid =~ /^(\d+)(c|d)$/) {
+ my ($itemnum,$itemtype) = ($1,$2);
+ my ($crsdef,$lti_in_use);
+ if ($itemtype eq 'c') {
+ $crsdef = 1;
+ my %crslti = &Apache::lonnet::get_course_lti($cnum,$cdom,'provider');
+ $lti_in_use = $crslti{$itemnum};
+ } else {
+ my %domlti = &Apache::lonnet::get_domain_lti($cdom,'linkprot');
+ $lti_in_use = $domlti{$itemnum};
+ }
+ my ($state,$others,$listed,$scope,$protect,$display,$target,$exit) = split(/,/,$deeplink);
+ my $passback;
+ if ($scope eq 'resource') {
+ if ($deeplink_symb eq $symb) {
+ $passback = 1;
+ }
+ } elsif ($scope eq 'map') {
+ if (&Apache::lonnet::clutter($deeplink_map) eq $map) {
+ $passback = 1;
+ }
+ } elsif ($scope eq 'recurse') {
+#FIXME check if $deeplink_map contains $map
+ $passback = 1;
+ }
+ return ($passback,$scope,$deeplink_map,$deeplink_symb,$crsdef,$itemnum,$lti_in_use);
+ }
+ }
+ }
+ }
+ }
+}
+
+=pod
+
+=item check_correctness_changes()
+
+ For all parts for which current results contain a solved status
+ of "incorrect_attempted", check if there was a transaction in which
+ solved was set to "correct_by_student" in the time since the last
+ transaction (retrieved when &initialize_storage() was called i.e.,
+ when &start_problem() was called), unless:
+ (a) questiontype parameter is set to survey or anonymous survey (+/- credit)
+ (b) problemstatus is set to no or no_feedback_ever
+ If such a transaction exists, and did not occur after "reset status"
+ by a user with grading privileges, then the current transaction is an
+ example of an out-of-order transaction (i.e., incorrect occurring after
+ correct). Accordingly, the current transaction should be hidden.
+
+=cut
+
+
+sub check_correctness_changes {
+ my ($symb,$courseid,$domain,$name,$record,$parts,$newversion,$oldversion) = @_;
+ my @parts_to_hide;
+ unless ((ref($record) eq 'HASH') && (ref($parts) eq 'ARRAY')) {
+ return @parts_to_hide;
+ }
+ if (@{$parts}) {
+ my $usec;
+ if (($env{'user.name'} eq $name) && ($env{'user.domain'} eq $domain) &&
+ ($env{'request.course.id'} eq $courseid)) {
+ $usec = $env{'request.course.sec'};
+ } else {
+ $usec = &Apache::lonnet::getsection($domain,$name,$courseid);
+ }
+ foreach my $id (@{$parts}) {
+ next if (($Apache::lonhomework::results{'resource.'.$id.'.type'} =~ /survey/) ||
+ (&Apache::lonnet::EXT("resource.$id.problemstatus",$symb,
+ $domain,$name,$usec,undef,$courseid) =~ /^no/));
+ my $reset;
+ for (my $i=$newversion-1; $i>=$oldversion; $i--) {
+ if (($record->{$i.':resource.'.$id.'.regrader'}) &&
+ ($record->{$i.':resource.'.$id.'.tries'} eq '') &&
+ ($record->{$i.':resource.'.$id.'.award'} eq '')) {
+ $reset = 1;
+ } elsif (($record->{$i.":resource.$id.solved"} eq 'correct_by_student') &&
+ ($record->{$i.":resource.$id.awarded"} >= 1)) {
+ unless ($reset) {
+ push(@parts_to_hide,$id);
+ last;
+ }
+ }
+ }
+ }
+ }
+ return @parts_to_hide;
+}
+
=pod
item store_aggregates()
@@ -649,7 +1470,7 @@ item store_aggregates()
sub store_aggregates {
my ($symb,$courseid) = @_;
- my (%aggregate,%anoncounter);
+ my (%aggregate,%anoncounter,%randtrycounter);
my @parts;
my $cdomain = $env{'course.'.$env{'request.course.id'}.'.domain'};
my $cname = $env{'course.'.$env{'request.course.id'}.'.num'};
@@ -679,8 +1500,13 @@ sub store_aggregates {
$aggregate{$symb."\0".$part."\0attempts"} = 1;
}
if (($Apache::lonhomework::results{'resource.'.$part.'.type'} eq 'anonsurvey') ||
- ($Apache::lonhomework::results{'resource.'.$part.'.type'} eq 'anonsurveycred')) {
- $anoncounter{$symb."\0".$part} = 1;
+ ($Apache::lonhomework::results{'resource.'.$part.'.type'} eq 'anonsurveycred') ||
+ ($Apache::lonhomework::results{'resource.'.$part.'.type'} eq 'randomizetry')) {
+ if ($Apache::lonhomework::results{'resource.'.$part.'.type'} eq 'randomizetry') {
+ $randtrycounter{$symb."\0".$part} = 1;
+ } else {
+ $anoncounter{$symb."\0".$part} = 1;
+ }
my $needsrelease = $Apache::lonnet::needsrelease{'parameter:type:'.$Apache::lonhomework::results{'resource.'.$part.'.type'}};
if ($needsrelease) {
my $curr_required = $env{'course.'.$env{'request.course.id'}.'.internal.releaserequired'};
@@ -696,13 +1522,17 @@ sub store_aggregates {
}
}
}
- if (keys (%aggregate) > 0) {
+ if (keys(%aggregate) > 0) {
&Apache::lonnet::cinc('nohist_resourcetracker',\%aggregate,
$cdomain,$cname);
}
if (keys(%anoncounter) > 0) {
- &Apache::lonnet::cinc('nohist_anonsurveys',\%anoncounter,
- $cdomain,$cname);
+ &Apache::lonnet::cput('nohist_anonsurveys',\%anoncounter,
+ $cdomain,$cname);
+ }
+ if (keys(%randtrycounter) > 0) {
+ &Apache::lonnet::cput('nohist_randomizetry',\%randtrycounter,
+ $cdomain,$cname);
}
}
@@ -720,7 +1550,7 @@ sub checkout_msg {
$lt{'warning'}
ENDCHECKOUT
}
@@ -734,27 +1564,29 @@ sub firstaccess_msg {
my $foldertitle=&Apache::lonnet::gettitle($map);
&Apache::lonxml::debug("map is $map title is $foldertitle");
- $result .= " ".&mt('The resources in "[_1]" are open for a limited time.'
- .' Once you click the "Show Resource" button below you have [_2] to complete all resources "[_1]".'
- ,$foldertitle,$time)."";
+ $result .= " ".&mt('The resources in "[_1]" are open for a limited time.',$foldertitle).""
+ .' '.&mt('Once you click the "Show Resource" button below you have [_2] to complete all resources "[_1]".'
+ ,$foldertitle,$time)." ";
} elsif ($interval[1] eq 'course') {
my $course = $env{'course.'.$env{'request.course.id'}.'.description'};
- $result .= " ".&mt('The resources in "[_1]" are open for a limited time.'
- .' Once you click the "Show Resource" button below you have [_2] to complete all resources "[_1]".'
- ,$course,$time)."";
+ $result .= " ".&mt('The resources in "[_1]" are open for a limited time.',$course).""
+ .' '.&mt('Once you click the "Show Resource" button below you have [_2] to complete all resources "[_1]".'
+ ,$course,$time)." ";
} else {
my $title=&Apache::lonnet::gettitle($symb);
- $result .= " ".&mt('This resource "[_1]" is open for a limited time.'
- .' Once you click the "Show Resource" button below you have [_2] to complete this resource "[_1]".'
- ,$title,$time)."";
+ $result .= " ".&mt('This resource "[_1]" is open for a limited time.',$title).""
+ .' '.&mt('Once you click the "Show Resource" button below you have [_2] to complete this resource "[_1]".'
+ ,$title,$time)." ";
}
my $uri = &Apache::lonenc::check_encrypt($env{'request.uri'});
my $buttontext = &mt('Show Resource');
my $timertext = &mt('Start Timer?');
+ my $shownsymb = &HTML::Entities::encode(&Apache::lonenc::check_encrypt($symb),'\'"<>&');
$result .= (<
-
+
+
ENDCHECKOUT
return $result;
@@ -784,15 +1616,18 @@ sub init_problem_globals {
&Apache::lonhomework::reset_show_problem_status();
$Apache::lonhomework::ignore_response_errors=1;
}
+ @Apache::functionplotresponse::callscripts=();
@Apache::inputtags::responselist = ();
@Apache::inputtags::importlist = ();
@Apache::inputtags::previous=();
@Apache::inputtags::previous_version=();
+ $Apache::inputtags::leniency='';
$Apache::structuretags::printanswer='No';
@Apache::structuretags::whileconds=();
@Apache::structuretags::whilebody=();
@Apache::structuretags::whileline=();
$Apache::lonhomework::scantronmode=0;
+ $Apache::lonhomework::randomizetrypart=0;
undef($Apache::lonhomework::name);
undef($Apache::lonhomework::default_type);
undef($Apache::lonhomework::type);
@@ -803,6 +1638,12 @@ sub reset_problem_globals {
undef(%Apache::lonhomework::history);
undef(%Apache::lonhomework::results);
undef($Apache::inputtags::part);
+ undef($Apache::inputtags::leniency);
+ if ($type eq 'Task') {
+ undef($Apache::inputtags::slot_name);
+ } elsif ($type eq 'problem') {
+ undef($Apache::lonhomework::rawrndseed);
+ }
#don't undef this, lonhomework.pm takes care of this, we use this to
#detect if we try to do 2 problems in one file
# undef($Apache::lonhomework::parsing_a_problem);
@@ -810,7 +1651,9 @@ sub reset_problem_globals {
undef($Apache::lonhomework::default_type);
undef($Apache::lonhomework::type);
undef($Apache::lonhomework::scantronmode);
+ undef($Apache::inputtags::randomizetrypart);
undef($Apache::lonhomework::ignore_response_errors);
+ undef(@Apache::functionplotresponse::callscripts);
&Apache::lonhomework::reset_show_problem_status();
}
@@ -899,32 +1742,82 @@ sub start_problem {
&Apache::run::run($expression,$safeeval);
my $status;
my $accessmsg;
+ my $resource_due;
my $name= &get_resource_name($parstack,$safeeval);
- my ($result,$form_tag_start);
+ my ($result,$form_tag_start,$slot_name,$slot,$probpartlist,$firstaccres);
+
+ if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' ||
+ $target eq 'tex') {
+ if ($env{'form.markaccess'}) {
+ my @interval=&Apache::lonnet::EXT("resource.0.interval");
+ my ($timelimit) = ($interval[0] =~ /^(\d+)/);
+ my $is_set = &Apache::lonnet::set_first_access($interval[1],$timelimit);
+ unless (($is_set eq 'ok') || ($is_set eq 'already_set')) {
+ $firstaccres = $is_set;
+ }
+ }
+
+ ($status,$accessmsg,$slot_name,$slot) =
+ &Apache::lonhomework::check_slot_access('0','problem');
+ push (@Apache::inputtags::status,$status);
+ }
+
if ($target eq 'web' || $target eq 'webgrade' || $target eq 'tex'
|| $target eq 'edit') {
- ($result,$form_tag_start) =
+ ($result,$form_tag_start,$probpartlist) =
&page_start($target,$token,$tagstack,$parstack,$parser,$safeeval,
$name);
+ } elsif (($target eq 'grade') && ($Apache::lonhomework::type eq 'randomizetry')) {
+ my ($symb)= &Apache::lonnet::whichuser();
+ if ($symb ne '') {
+ my $navmap = Apache::lonnavmaps::navmap->new();
+ if (ref($navmap)) {
+ my $res = $navmap->getBySymb($symb);
+ if (ref($res)) {
+ $probpartlist = $res->parts();
+ }
+ }
+ }
}
if ($target eq 'tex' and $env{'request.symb'} =~ m/\.page_/) {$result='';}
- if ($target eq 'analyze') { my $rndseed=&setup_rndseed($safeeval); }
+ if ($target eq 'analyze') { my $rndseed=&setup_rndseed($safeeval,$target); }
if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' ||
$target eq 'tex') {
- if ($env{'form.markaccess'}) {
- my @interval=&Apache::lonnet::EXT("resource.0.interval");
- &Apache::lonnet::set_first_access($interval[1]);
- }
+
+ my ($symb) = &Apache::lonnet::whichuser();
#handle rand seed in construction space
- my $rndseed=&setup_rndseed($safeeval);
- my ($symb)=&Apache::lonnet::whichuser();
+ if (($env{'request.state'} eq 'construct') || ($symb eq '')) {
+ my $partorder=&Apache::lonnet::metadata($env{'request.uri'},'partorder');
+ if ($partorder ne '') {
+ @{$probpartlist} = split(/,/,$partorder);
+ }
+ }
+ my $rndseed=&setup_rndseed($safeeval,$target,$probpartlist);
+ if (($target eq 'grade') && &Apache::response::submitted()) {
+ if ($Apache::lonhomework::type eq 'randomizetry') {
+ $Apache::lonhomework::results{'resource.0.rndseed'}=$rndseed;
+ } else {
+ my @parts;
+ if (ref($probpartlist) eq 'ARRAY') {
+ @parts = @{$probpartlist};
+ }
+ unless (@parts) {
+ $Apache::lonhomework::results{'resource.0.rndseed'}=$Apache::lonhomework::rawrndseed;
+ }
+ }
+ }
+
if ($env{'request.state'} ne "construct" &&
($symb eq '' || $Apache::lonhomework::type eq 'practice')) {
+ my $rndseedval = $rndseed;
+ if (($symb eq '') && ($Apache::lonhomework::type eq 'randomizetry')) {
+ $rndseedval = $env{'form.rndseed'};
+ }
$form_tag_start.=''.
+ $rndseedval.'" />'.
'';
if (exists($env{'form.username'})) {
@@ -946,11 +1839,20 @@ sub start_problem {
$form_tag_start.=&practice_problem_header();
}
$form_tag_start.=' ';
- }
-
- ($status,$accessmsg,my $slot_name,my $slot) =
- &Apache::lonhomework::check_slot_access('0','problem');
- push (@Apache::inputtags::status,$status);
+ }
+ if (($env{'request.state'} ne "construct") &&
+ ($Apache::lonhomework::type eq 'randomizetry') &&
+ ($status eq 'CAN_ANSWER')) {
+ my @parts;
+ if (ref($probpartlist) eq 'ARRAY') {
+ @parts = @{$probpartlist};
+ }
+ unless (@parts) {
+ my $reqtries = &Apache::lonnet::EXT("resource.$Apache::inputtags::part.randomizeontries");
+ my $problemstatus = &get_problem_status($Apache::inputtags::part);
+ $form_tag_start.=&randomizetry_problem_header($problemstatus,$reqtries,$symb);
+ }
+ }
my $expression='$external::datestatus="'.$status.'";';
$expression.='$external::gradestatus="'.$Apache::lonhomework::history{"resource.0.solved"}.'";';
@@ -963,26 +1865,46 @@ sub start_problem {
( $status eq 'BANNED') ||
( $status eq 'UNAVAILABLE') ||
( $status eq 'NOT_IN_A_SLOT') ||
+ ( $status eq 'NOTRESERVABLE') ||
+ ( $status eq 'RESERVABLE') ||
+ ( $status eq 'RESERVABLE_LATER') ||
( $status eq 'INVALID_ACCESS')) {
my $bodytext=&Apache::lonxml::get_all_text("/problem",$parser,
$style);
if ( $target eq "web" ) {
my $msg;
if ($status eq 'UNAVAILABLE') {
- $msg.=''.&mt('Unable to determine if this resource is open due to network problems. Please try again later.').'';
+ $msg.=''.&mt('Unable to determine if this resource is open due to network problems. Please try again later.').' ';
} elsif ($status eq 'NOT_IN_A_SLOT') {
- $msg.=''.&mt('You are not currently signed up to work at this time and/or place.').'';
+ $msg.=''.&mt('You are not currently signed up to work at this time and/or place.').' ';
+ } elsif (($status eq 'RESERVABLE') || ($status eq 'RESERVABLE_LATER') ||
+ ($status eq 'NOTRESERVABLE')) {
+ $msg.=''.&mt('Access requires reservation to work at specific time/place.').' ';
} elsif ($status ne 'NOT_YET_VIEWED') {
- $msg.=''.&mt('Not open to be viewed').'';
- }
+ $msg.=''.&mt('Not open to be viewed').' ';
+ }
if ($status eq 'CLOSED' || $status eq 'INVALID_ACCESS') {
$msg.=&mt('The problem ').$accessmsg;
} elsif ($status eq 'UNCHECKEDOUT') {
$msg.=&checkout_msg();
} elsif ($status eq 'NOT_YET_VIEWED') {
+ if ($firstaccres) {
+ $msg .= ''.
+ &mt('A problem occurred when trying to start the timer.').' ';
+ }
$msg.=&firstaccess_msg($accessmsg,$symb);
} elsif ($status eq 'NOT_IN_A_SLOT') {
$msg.=&Apache::bridgetask::add_request_another_attempt_button("Sign up for time to work");
+ } elsif ($status eq 'RESERVABLE') {
+ $msg.=&mt('Available to make a reservation.').' '.&mt('Reservation window closes [_1].',
+ &Apache::lonnavmaps::timeToHumanString($accessmsg,'end')).
+ ' '.
+ &Apache::bridgetask::add_request_another_attempt_button("Sign up for time to work");
+ } elsif ($status eq 'RESERVABLE_LATER') {
+ $msg.=&mt('Window to make a reservation will open [_1].',
+ &Apache::lonnavmaps::timeToHumanString($accessmsg,'start'));
+ } elsif ($status eq 'NOTRESERVABLE') {
+ $msg.=&mt('Not available to make a reservation.');
}
$result.=$msg.' ';
} elsif ($target eq 'tex') {
@@ -1007,13 +1929,35 @@ sub start_problem {
'problem');
}
} elsif ($target eq 'web') {
- if ($status eq 'CAN_ANSWER'
- && $slot_name ne ''
- && $Apache::lonhomework::history{'resource.0.checkedin'} eq '') {
- # unproctored slot access, self checkin
- &Apache::bridgetask::check_in('problem',undef,undef,
- $slot_name);
- }
+ if ($status eq 'CAN_ANSWER') {
+ $resource_due = &Apache::lonhomework::due_date(0, $env{'request.symb'});
+ if ($slot_name ne '') {
+ my $checked_in =
+ $Apache::lonhomework::history{'resource.0.checkedin'};
+ if ($checked_in eq '') {
+ # unproctored slot access, self checkin
+ &Apache::bridgetask::check_in('problem',undef,undef,
+ $slot_name);
+ $checked_in =
+ $Apache::lonhomework::results{"resource.0.checkedin"};
+ }
+ if ((ref($slot) eq 'HASH') && ($checked_in ne '')) {
+ if ($slot->{'starttime'} < time()) {
+ if (!$resource_due) {
+ $resource_due = $slot->{'endtime'};
+ } elsif ($slot->{'endtime'} < $resource_due) {
+ $resource_due = $slot->{'endtime'};
+ }
+ }
+ }
+ }
+ if ($resource_due) {
+ my $time_left = $resource_due - time();
+ if ($resource_due && ($time_left > 0) && ($target eq 'web')) {
+ $result .= &Apache::lonhtmlcommon::set_due_date($resource_due);
+ }
+ }
+ }
$result.="\n $form_tag_start \t".
'';
# create a page header and exit
@@ -1023,6 +1967,10 @@ sub start_problem {
$result.= ''.
&practice_problem_header().' ';
+ } elsif ($Apache::lonhomework::type eq 'randomizetry') {
+ my $reqtries = &Apache::lonnet::EXT("resource.$Apache::inputtags::part.randomizeontries");
+ my $problemstatus = &get_problem_status($Apache::inputtags::part);
+ $result.=&randomizetry_problem_header($problemstatus,$reqtries);
}
}
# if we are viewing someone else preserve that info
@@ -1031,9 +1979,20 @@ sub start_problem {
$result .= ''."\n";
}
+ foreach my $field ('trial','questiontype') {
+ if ($env{"form.grade_$field"} ne '') {
+ $result .= ''."\n";
+ }
+ }
}
+ if ($env{'form.grade_imsexport'}) {
+ $result = '';
+ }
} elsif ($target eq 'tex') {
$result .= 'INSERTTEXFRONTMATTERHERE';
+ $result .= &select_metadata_hyphenation();
+
}
} elsif ($target eq 'edit') {
@@ -1075,7 +2034,7 @@ sub end_problem {
my $id = $Apache::inputtags::part;
my $weight = &Apache::lonnet::EXT("resource.$id.weight");
my $packages=&Apache::lonnet::metadata($env{'request.uri'},'packages');
- my @packages = split /,/,$packages;
+ my @packages = split(/,/,$packages);
my $allow_print_points = 0;
foreach my $partial_key (@packages) {
if ($partial_key=~m/^part_0$/) {
@@ -1090,6 +2049,7 @@ sub end_problem {
}
my $name_of_resourse= &Apache::lonxml::latex_special_symbols(&get_resource_name($parstack,$safeeval),'header');
my $begin_doc=' \typeout{STAMPOFPASSEDRESOURCESTART Resource "'.$name_of_resourse.'" located in '.$env{'request.uri'}.' STAMPOFPASSEDRESOURCEEND} \noindent ';
+ &clear_required_languages();
my $toc_line='\vskip 1 mm\noindent '.$startminipage.
'\addcontentsline{toc}{subsection}{'.$name_of_resourse.'}';
@@ -1136,7 +2096,7 @@ sub end_problem {
} else {
$frontmatter.= $begin_doc.$toc_line;
if ($Apache::lonhomework::type eq 'exam' and $allow_print_points==1) {
- $frontmatter .= '\fbox{\textit{'.$weight.' pt}}';
+ $frontmatter .= '\fbox{\textit{'.&mt('[quant,_1,pt,pt]',$weight ).'}}';
}
}
} else {
@@ -1146,7 +2106,7 @@ sub end_problem {
if (not $env{'request.symb'} =~ m/\.page_/) {
$frontmatter .= $begin_doc.$toc_line;
if (($Apache::lonhomework::type eq 'exam') and ($allow_print_points==1)) {
- $frontmatter .= '\fbox{\textit{'.$weight.' pt}}';
+ $frontmatter .= '\fbox{\textit{'.&mt('[quant,_1,pt,pt]',$weight ).'}}';
}
} else {
$frontmatter .= '\vskip 1mm \\\\\\\\'.$startminipage;
@@ -1170,7 +2130,8 @@ sub end_problem {
}
} elsif ( ($target eq 'web' || $target eq 'tex') &&
$Apache::inputtags::part eq '0' &&
- $status ne 'UNCHECKEDOUT' && $status ne 'NOT_YET_VIEWED') {
+ $status ne 'UNCHECKEDOUT' && $status ne 'NOT_YET_VIEWED'
+ && !$env{'form.grade_imsexport'}) {
# if part is zero, no s existed, so we need show the current
# grading status
my $gradestatus = &Apache::inputtags::gradestatus($Apache::inputtags::part,$target);
@@ -1180,13 +2141,19 @@ sub end_problem {
(($target eq 'web') && ($env{'request.state'} ne 'construct')) ||
($target eq 'answer') || ($target eq 'tex')
) {
- if ($target ne 'tex' &&
- $env{'form.answer_output_mode'} ne 'tex') {
+ if (($target ne 'tex') &&
+ ($env{'form.answer_output_mode'} ne 'tex') &&
+ (!$env{'form.grade_imsexport'})) {
$result.="";
- $result.= &Apache::lonhtmlcommon::htmlareaselectactive(&Apache::lonhtmlcommon::get_htmlareafields());
}
if ($target eq 'web') {
- $result.= &Apache::loncommon::end_page({'discussion' => 1});
+ #
+ # Closing |