--- loncom/interface/loncoursedata.pm 2005/04/21 17:35:58 1.141.2.3 +++ loncom/interface/loncoursedata.pm 2005/03/03 18:57:36 1.144 @@ -1,6 +1,6 @@ # The LearningOnline Network with CAPA # -# $Id: loncoursedata.pm,v 1.141.2.3 2005/04/21 17:35:58 albertel Exp $ +# $Id: loncoursedata.pm,v 1.144 2005/03/03 18:57:36 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -66,152 +66,6 @@ and/or itself. =cut -#################################################### -#################################################### - -=pod - -=item &get_sequence_assessment_data() - -Use lonnavmaps to build a data structure describing the order and -assessment contents of each sequence in the current course. - -The returned structure is a hash reference. - -{ title => 'title', - symb => 'symb', - src => '/s/o/u/r/c/e', - type => (container|assessment), - num_assess => 2, # only for container - parts => [11,13,15], # only for assessment - response_ids => [12,14,16], # only for assessment - contents => [........] # only for container -} - -$hash->{'contents'} is a reference to an array of hashes of the same structure. - -Also returned are array references to the sequences and assessments contained -in the course. - - -=cut - -#################################################### -#################################################### -sub get_sequence_assessment_data { - my $fn=$ENV{'request.course.fn'}; - ## - ## use navmaps - my $navmap = Apache::lonnavmaps::navmap->new(); - if (!defined($navmap)) { - return 'Can not open Coursemap'; - } - # We explicity grab the top level map because I am not sure we - # are pulling it from the iterator. - my $top_level_map = $navmap->getById('0.0'); - # - my $iterator = $navmap->getIterator(undef, undef, undef, 1); - my $curRes = $iterator->next(); # Top level sequence - ## - ## Prime the pump - ## - ## We are going to loop until we run out of sequences/pages to explore for - ## resources. This means we have to start out with something to look - ## at. - my $title = $ENV{'course.'.$ENV{'request.course.id'}.'.description'}; - my $symb = $top_level_map->symb(); - my $src = $top_level_map->src(); - my $randompick = $top_level_map->randompick(); - # - my @Sequences; - my @Assessments; - my @Nested_Sequences = (); # Stack of sequences, keeps track of depth - my $top = { title => $title, - src => $src, - symb => $symb, - type => 'container', - num_assess => 0, - num_assess_parts => 0, - contents => [], - randompick => $randompick, - }; - push (@Sequences,$top); - push (@Nested_Sequences, $top); - # - # We need to keep track of which sequences contain homework problems - # - my $previous_too; - my $previous; - while (1) { - $previous_too = $previous; - $previous = $curRes; - $curRes = $iterator->next(); - if (!$curRes) { last; } - my $currentmap = $Nested_Sequences[-1]; # Last one on the stack - if ($curRes == $iterator->BEGIN_MAP()) { - if (! ref($previous)) { - $previous = $previous_too; - } - if (! ref($previous)) { - next; - } - # get the map itself, instead of BEGIN_MAP - $title = $previous->compTitle; - $symb = $previous->symb(); - $src = $previous->src(); - $randompick = $previous->randompick(); - my $newmap = { title => $title, - src => $src, - symb => $symb, - type => 'container', - num_assess => 0, - randompick => $randompick, - contents => [], - }; - push (@{$currentmap->{'contents'}},$newmap); # this is permanent - push (@Sequences,$newmap); - push (@Nested_Sequences, $newmap); # this is a stack - next; - } - if ($curRes == $iterator->END_MAP()) { - pop(@Nested_Sequences); - next; - } - next if (! ref($curRes)); - next if (! $curRes->is_problem() && $curRes->src() !~ /\.survey$/); - # Okay, from here on out we only deal with assessments - $title = $curRes->compTitle(); - $symb = $curRes->symb(); - $src = $curRes->src(); - my $parts = $curRes->parts(); - my %partdata; - foreach my $part (@$parts) { - my @Responses = $curRes->responseType($part); - my @Ids = $curRes->responseIds($part); - $partdata{$part}->{'ResponseTypes'}= \@Responses; - $partdata{$part}->{'ResponseIds'} = \@Ids; - $partdata{$part}->{'Survey'} = $curRes->is_survey($part); - # Count how many responses of each type there are in this part - foreach (@Responses) { - $partdata{$part}->{$_}++; - } - } - my $assessment = { title => $title, - src => $src, - symb => $symb, - type => 'assessment', - parts => $parts, - num_parts => scalar(@$parts), - partdata => \%partdata, - }; - push(@Assessments,$assessment); - push(@{$currentmap->{'contents'}},$assessment); - $currentmap->{'num_assess'}++; - $currentmap->{'num_assess_parts'}+= scalar(@$parts); - } - return ($top,\@Sequences,\@Assessments); -} - sub LoadDiscussion { my ($courseID)=@_; my %Discuss=(); @@ -778,6 +632,13 @@ sub init_dbs { =item &delete_caches() +This routine drops all the tables associated with a course from the +MySQL database. + +Input: course id (optional, determined by environment if omitted) + +Returns: nothing + =cut ################################################ @@ -1059,7 +920,6 @@ sub clear_internal_caches { undef(%students_by_id); } - ################################################ ################################################ @@ -2029,10 +1889,24 @@ sub populate_weight_table { } # &setup_table_names($courseid); - my ($top,$sequences,$assessments) = get_sequence_assessment_data(); - if (! defined($top) || ! ref($top)) { - # There has been an error, better report it - &Apache::lonnet::logthis('top is undefined'); + my $navmap = Apache::lonnavmaps::navmap->new(); + if (!defined($navmap)) { + &Apache::lonnet::logthis('loncoursedata::populate_weight_table:'.$/. + ' unable to get navmaps resource'.$/. + ' '.join(' ',(caller))); + return; + } + my @sequences = $navmap->retrieveResources(undef, + sub { shift->is_map(); },1,0,1); + my @resources; + foreach my $seq (@sequences) { + push(@resources,$navmap->retrieveResources($seq, + sub {shift->is_problem();}, + 0,0,0)); + } + if (! scalar(@resources)) { + &Apache::lonnet::logthis('loncoursedata::populate_weight_table:'.$/. + ' no resources returned for '.$courseid); return; } # Since we use lonnet::EXT to retrieve problem weights, @@ -2042,12 +1916,12 @@ sub populate_weight_table { my $request = 'INSERT IGNORE INTO '.$weight_table. "(symb_id,part_id,weight) VALUES "; my $weight; - foreach my $res (@$assessments) { - my $symb_id = &get_symb_id($res->{'symb'}); - foreach my $part (@{$res->{'parts'}}) { + foreach my $res (@resources) { + my $symb_id = &get_symb_id($res->symb); + foreach my $part (@{$res->parts}) { my $part_id = &get_part_id($part); $weight = &Apache::lonnet::EXT('resource.'.$part.'.weight', - $res->{'symb'}, + $res->symb, undef,undef,undef); if (!defined($weight) || ($weight eq '')) { $weight=1; @@ -2219,7 +2093,7 @@ Returns: the sum of the score on the pro ######################################################## ######################################################## sub get_sum_of_scores { - my ($resource,$part,$students,$courseid,$starttime,$endtime) = @_; + my ($symb,$part,$students,$courseid,$starttime,$endtime) = @_; if (! defined($courseid)) { $courseid = $ENV{'request.course.id'}; } @@ -2238,7 +2112,7 @@ sub get_sum_of_scores { my $request = 'SELECT SUM(a.awarded*w.weight),SUM(w.weight) FROM '. $performance_table.' AS a '. 'NATURAL LEFT JOIN '.$weight_table.' AS w '; - $request .= 'WHERE a.symb_id='.&get_symb_id($resource->{'symb'}). + $request .= 'WHERE a.symb_id='.&get_symb_id($symb). ' AND a.part_id='.&get_part_id($part); if (defined($time_limits)) { $request .= ' AND '.$time_limits; @@ -2583,32 +2457,46 @@ sub RT_tries { return 2; } sub RT_timestamp { return 3; } sub get_response_time_data { - my ($students,$symb,$part,$courseid) = @_; + my ($sections,$enrollment,$symb,$part,$courseid) = @_; return undef if (! defined($symb) || ! defined($part)); $courseid = $ENV{'request.course.id'} if (! defined($courseid)); # &setup_table_names($courseid); my $symb_id = &get_symb_id($symb); + if (! defined($symb_id)) { + &Apache::lonnet::logthis('Unable to find symb for '.$symb.' in '.$courseid); + return undef; + } my $part_id = &get_part_id($part); + if (! defined($part_id)) { + &Apache::lonnet::logthis('Unable to find id for '.$part.' in '.$courseid); + return undef; + } # my $dbh = &Apache::lonmysql::get_dbh(); return undef if (! defined($dbh)); + my ($student_requirements,$enrollment_requirements) = + &limit_by_section_and_status($sections,$enrollment,'d'); my $request = 'SELECT '. 'a.student_id, a.awarded, a.tries, b.timestamp '. 'FROM '.$fulldump_part_table.' AS a '. - 'NATURAL LEFT JOIN '.$fulldump_timestamp_table.' AS b '. -# 'ON a.symb_id=b.symb_id AND a.student_id=b.student_id AND '. -# 'a.transaction = b.transaction '. + 'LEFT JOIN '.$fulldump_timestamp_table.' AS b '. + 'ON a.symb_id=b.symb_id AND a.student_id=b.student_id AND '. + 'a.transaction = b.transaction '. + 'LEFT JOIN '.$student_table.' as d '. + 'ON a.student_id=d.student_id '. 'WHERE '. 'a.symb_id='.$symb_id.' AND a.part_id='.$part_id; - if (defined($students)) { - $request .= ' AND ('. - join(' OR ', map {'a.student_id='. - &get_student_id($_->{'username'}, - $_->{'domain'}) - } @$students - ).')'; + if (defined($student_requirements) || defined($enrollment_requirements)) { + $request .= ' AND '; + if (defined($student_requirements)) { + $request .= $student_requirements.' AND '; + } + if (defined($enrollment_requirements)) { + $request .= $enrollment_requirements.' AND '; + } + $request =~ s/( AND )$//; } $request .= ' ORDER BY b.timestamp'; # &Apache::lonnet::logthis("request =\n".$request);