--- loncom/interface/statistics/lonstathelpers.pm 2004/08/03 19:53:12 1.18 +++ loncom/interface/statistics/lonstathelpers.pm 2004/10/04 19:11:38 1.28 @@ -1,6 +1,6 @@ # The LearningOnline Network with CAPA # -# $Id: lonstathelpers.pm,v 1.18 2004/08/03 19:53:12 matthew Exp $ +# $Id: lonstathelpers.pm,v 1.28 2004/10/04 19:11:38 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -40,7 +40,6 @@ routines that are needed across multiple =head1 OVERVIEW - =over 4 =cut @@ -119,6 +118,7 @@ sub ProblemSelector { my ($AcceptedResponseTypes) = @_; my $Str; $Str = "\n\n"; + my $rb_count =0; foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess('all')) { next if ($seq->{'num_assess'}<1); my $seq_str = ''; @@ -126,7 +126,6 @@ sub ProblemSelector { next if ($res->{'type'} ne 'assessment'); foreach my $part (@{$res->{'parts'}}) { my $partdata = $res->{'partdata'}->{$part}; - next if ($partdata->{'Survey'}); for (my $i=0;$i{'ResponseTypes'}});$i++){ my $respid = $partdata->{'ResponseIds'}->[$i]; my $resptype = $partdata->{'ResponseTypes'}->[$i]; @@ -143,16 +142,17 @@ sub ProblemSelector { if (! defined($title) || $title eq '') { ($title) = ($res->{'src'} =~ m:/([^/]*)$:); } - $seq_str .= ''. + qq{}. + ''. + '\n"; + $rb_count++; } } } @@ -171,6 +171,177 @@ sub ProblemSelector { =pod +=item &MultipleProblemSelector($navmap,$selected,$inputname) + +Generate HTML with checkboxes for problem selection. + +Input: + +$navmap: a navmap object. If undef, navmaps will be called to create a +new object. + +$selected: Scalar, Array, or hash reference of currently selected items. + +$inputname: The name of the form elements to use for the checkboxs. + +Returns: A string containing html for a table which lists the sequences +and their contents. A checkbox is provided for each problem. + +=cut + +#################################################### +#################################################### +sub MultipleProblemSelector { + my ($navmap,$inputname,$formname)=@_; + my $cid = $ENV{'request.course.id'}; + my $Str; + # Massage the input as needed. + if (! defined($navmap)) { + $navmap = Apache::lonnavmaps::navmap->new(); + if (! defined($navmap)) { + $Str .= + '

'.&mt('Error: cannot process course structure').'

'; + return $Str; + } + } + my $selected = {map { ($_,1) } (&get_selected_symbs($inputname))}; + # Header + $Str .= <<"END"; + +END + $Str .= + ''.&mt('Select All').''. + (' 'x4). + ''.&mt('Unselect All').''; + $Str .= $/.'
'. - ''. - ''. - $resptype.''. - ''.$title.' '; -# ''.$resptype.' '.$res->{'title'}.' '; + $seq_str .= '
'; if (scalar(@{$partdata->{'ResponseIds'}}) > 1) { $seq_str .= &mt('response').' '.$respid; } + $seq_str .= (' 'x2). + qq{view}; $seq_str .= "
'.$/; + my $iterator = $navmap->getIterator(undef, undef, undef, 1); + my $sequence_string; + my $seq_id = 0; + my @Accumulator = (&new_accumulator($ENV{'course.'.$cid.'.description'}, + '', + '', + $seq_id++, + $inputname)); + my @Sequence_Data; + while (my $curRes = $iterator->next()) { + if ($curRes == $iterator->END_MAP) { + if (ref($Accumulator[-1]) eq 'CODE') { + my $old_accumulator = pop(@Accumulator); + push(@Sequence_Data,&{$old_accumulator}()); + } + } elsif ($curRes == $iterator->BEGIN_MAP) { + # Not much to do here. + } + next if (! ref($curRes)); + if ($curRes->is_map) { + push(@Accumulator,&new_accumulator($curRes->compTitle, + $curRes->src, + $curRes->symb, + $seq_id++, + $inputname)); + } elsif ($curRes->is_problem) { + if (@Accumulator && $Accumulator[-1] ne '') { + &{$Accumulator[-1]}($curRes, + exists($selected->{$curRes->symb})); + } + } + } + my $course_seq = pop(@Sequence_Data); + foreach my $seq ($course_seq,@Sequence_Data) { + #my $seq = pop(@Sequence_Data); + next if (! defined($seq) || ref($seq) ne 'HASH'); + $Str.= ''.$/; + $Str.= $seq->{'html'}; + } + $Str .= '
'. + ''.$seq->{'title'}.''.(' 'x2). + ''. + &mt('Select').''.(' 'x2). + ''. + &mt('Unselect').''.(' 'x2). + '
'.$/; + return $Str; +} + +sub get_title { + my ($title,$src) = @_; + if ($title eq '') { + ($title) = ($src =~ m|/([^/]+)$|); + } else { + $title =~ s/\:/:/g; + } + return $title; +} + +sub new_accumulator { + my ($title,$src,$symb,$seq_id,$inputname) = @_; + my $target; + my $item_id=0; + return + sub { + if (@_) { + my ($res,$checked) = @_; + $target.=''. + (' 'x2).'view'. + ''.$/; + } else { + if (defined($target)) { + return { title => $title, + symb => $symb, + src => $src, + id => $seq_id, + html => $target, }; + } + return undef; + } + }; +} + +sub get_selected_symbs { + my ($inputfield) = @_; + my $field = 'form.'.$inputfield; + my @Symbs; + if (exists($ENV{$field})) { + if (! ref($ENV{$field})) { + @Symbs = (&Apache::lonnet::unescape($ENV{$field})); + } else { + @Symbs = (map {&Apache::lonnet::unescape($_);} @{$ENV{$field}}); + } + } + return @Symbs; +} + +#################################################### +#################################################### + +=pod + =item &make_target_id($target) Inputs: Hash ref with the following entries: @@ -214,11 +385,23 @@ Returns: A hash reference, $target, cont #################################################### sub get_target_from_id { my ($id) = @_; - my ($symb,$part,$respid,$resptype) = split(':',$id); - return ({ symb =>&Apache::lonnet::unescape($symb), - part =>&Apache::lonnet::unescape($part), - respid =>&Apache::lonnet::unescape($respid), - resptype =>&Apache::lonnet::unescape($resptype)}); + if (! ref($id)) { + my ($symb,$part,$respid,$resptype) = split(':',$id); + return ({ symb => &Apache::lonnet::unescape($symb), + part => &Apache::lonnet::unescape($part), + respid => &Apache::lonnet::unescape($respid), + resptype => &Apache::lonnet::unescape($resptype)}); + } elsif (ref($id) eq 'ARRAY') { + my @Return; + foreach my $selected (@$id) { + my ($symb,$part,$respid,$resptype) = split(':',$selected); + push(@Return,{ symb => &Apache::lonnet::unescape($symb), + part => &Apache::lonnet::unescape($part), + respid => &Apache::lonnet::unescape($respid), + resptype => &Apache::lonnet::unescape($resptype)}); + } + return \@Return; + } } #################################################### @@ -262,14 +445,12 @@ sub get_prev_curr_next { next if ($res->{'type'} ne 'assessment'); foreach my $part (@{$res->{'parts'}}) { my $partdata = $res->{'partdata'}->{$part}; - if ($partdata->{'Survey'}) { - if ($granularity eq 'part_survey'){ - push (@Resource, - { symb => $res->{symb}, - part => $part, - resource => $res, - } ); - } + if ($partdata->{'Survey'} && ($granularity eq 'part_survey')){ + push (@Resource, + { symb => $res->{symb}, + part => $part, + resource => $res, + } ); } elsif ($granularity eq 'part') { push (@Resource, { symb => $res->{symb}, @@ -439,6 +620,16 @@ keys $partid.'.'.$respid.'.answer'. ##################################################### sub analyze_problem_as_student { my ($resource,$sname,$sdom,$partid,$respid) = @_; + if (ref($resource) ne 'HASH') { + my $res = $resource; + $resource = { 'src' => $res->src, + 'symb' => $res->symb, + 'parts' => $res->parts }; + foreach my $part (@{$resource->{'parts'}}) { + $resource->{'partdata'}->{$part}->{'ResponseIds'}= + [$res->responseIds($part)]; + } + } my $returnvalue; my $url = $resource->{'src'}; my $symb = $resource->{'symb'}; @@ -917,13 +1108,15 @@ sub get_problem_data { $Partdata{$part}->{'_Options'}=$value; } elsif ($key eq 'concepts') { $Partdata{$part}->{'_Concepts'}=$value; + } elsif ($key eq 'items') { + $Partdata{$part}->{'_Items'}=$value; } elsif ($key =~ /^concept\.(.*)$/) { my $concept = $1; foreach my $foil (@$value) { $Partdata{$part}->{'_Foils'}->{$foil}->{'_Concept'}= $concept; } - } elsif ($key =~ /^(incorrect|answer|ans_low|ans_high)$/) { + } elsif ($key =~ /^(incorrect|answer|ans_low|ans_high|str_type)$/) { $Partdata{$part}->{$key}=$value; } } else { @@ -935,13 +1128,51 @@ sub get_problem_data { } elsif ($key =~ /^foil\.value\.(.*)$/) { my $foil = $1; $Partdata{$part}->{'_Foils'}->{$foil}->{'value'}=$value; + } elsif ($key eq 'answercomputed') { + $Partdata{$part}->{'answercomputed'} = $value; } } } } + # Further debugging code + if (0) { + &Apache::lonnet::logthis('lonstathelpers::get_problem_data'); + &log_hash_ref(\%Partdata); + } return %Partdata; } +sub log_array_ref { + my ($arrayref,$prefix) = @_; + return if (ref($arrayref) ne 'ARRAY'); + if (! defined($prefix)) { $prefix = ''; }; + foreach my $v (@$arrayref) { + if (ref($v) eq 'ARRAY') { + &log_array_ref($v,$prefix.' '); + } elsif (ref($v) eq 'HASH') { + &log_hash_ref($v,$prefix.' '); + } else { + &Apache::lonnet::logthis($prefix.'"'.$v.'"'); + } + } +} + +sub log_hash_ref { + my ($hashref,$prefix) = @_; + return if (ref($hashref) ne 'HASH'); + if (! defined($prefix)) { $prefix = ''; }; + while (my ($k,$v) = each(%$hashref)) { + if (ref($v) eq 'ARRAY') { + &Apache::lonnet::logthis($prefix.'"'.$k.'" = array'); + &log_array_ref($v,$prefix.' '); + } elsif (ref($v) eq 'HASH') { + &Apache::lonnet::logthis($prefix.'"'.$k.'" = hash'); + &log_hash_ref($v,$prefix.' '); + } else { + &Apache::lonnet::logthis($prefix.'"'.$k.'" => "'.$v.'"'); + } + } +} #################################################### #################################################### @@ -1071,7 +1302,7 @@ Returns: An array of scalars containing #################################################### #################################################### sub manage_caches { - my ($r,$formname,$inputname) = @_; + my ($r,$formname,$inputname,$update_message) = @_; &Apache::loncoursedata::clear_internal_caches(); my $sectionkey = join(',', @@ -1088,8 +1319,12 @@ sub manage_caches { (exists($ENV{'form.prevenrollstatus'}) && $ENV{'form.prevenrollstatus'} ne $statuskey) ) { + if (defined($update_message)) { + $r->print($update_message); + } &Apache::lonstatistics::Gather_Full_Student_Data($r,$formname, $inputname); + } # my @Buttons =