--- loncom/interface/loncoursedata.pm 2003/05/27 15:48:12 1.72 +++ loncom/interface/loncoursedata.pm 2003/10/03 15:33:25 1.81.2.2 @@ -1,6 +1,6 @@ # The LearningOnline Network with CAPA # -# $Id: loncoursedata.pm,v 1.72 2003/05/27 15:48:12 matthew Exp $ +# $Id: loncoursedata.pm,v 1.81.2.2 2003/10/03 15:33:25 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -109,6 +109,10 @@ sub get_sequence_assessment_data { 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 ## @@ -118,8 +122,9 @@ sub get_sequence_assessment_data { ## 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'; - my $src = 'not applicable'; + my $symb = $top_level_map->symb(); + my $src = $top_level_map->src(); + my $randompick = $top_level_map->randompick(); # my @Sequences; my @Assessments; @@ -130,27 +135,43 @@ sub get_sequence_assessment_data { type => 'container', num_assess => 0, num_assess_parts => 0, - contents => [], }; + 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 (scalar(@Nested_Sequences)) { + $previous_too = $previous; $previous = $curRes; $curRes = $iterator->next(); 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->title(); $symb = $previous->symb(); $src = $previous->src(); + # pick up the filename if there is no title available + if (! defined($title) || $title eq '') { + ($title) = ($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 @@ -455,6 +476,13 @@ sub init_dbs { my $courseid = shift; &setup_table_names($courseid); # + # Drop any of the existing tables + foreach my $table ($symb_table,$part_table,$student_table, + $updatetime_table,$performance_table, + $parameters_table) { + &Apache::lonmysql::drop_table($table); + } + # # Note - changes to this table must be reflected in the code that # stores the data (calls &Apache::lonmysql::store_row with this table # id @@ -527,6 +555,9 @@ sub init_dbs { { name => 'part_id', type => 'MEDIUMINT UNSIGNED', restrictions => 'NOT NULL' }, + { name => 'part', + type => 'VARCHAR(100)', + restrictions => 'NOT NULL'}, { name => 'solved', type => 'TINYTEXT' }, { name => 'tries', @@ -841,6 +872,36 @@ sub get_student { =pod +=item &clear_internal_caches() + +Causes the internal caches used in get_student_id, get_student, +get_symb_id, get_symb, get_part_id, and get_part to be undef'd. + +Needs to be called before the first operation with the MySQL database +for a given Apache request. + +=cut + +################################################ +################################################ +sub clear_internal_caches { + $have_read_part_table = 0; + undef(%ids_by_part); + undef(%parts_by_id); + $have_read_symb_table = 0; + undef(%ids_by_symb); + undef(%symbs_by_id); + $have_read_student_table = 0; + undef(%ids_by_student); + undef(%students_by_id); +} + + +################################################ +################################################ + +=pod + =item &update_student_data() Input: $sname, $sdom, $courseid @@ -889,7 +950,7 @@ sub update_student_data { $sname.':'.$sdom.' in course '.$courseid. ':'.$tmp[0]); $returnstatus = 'error getting data'; - return $returnstatus; + return ($returnstatus,undef); } if (scalar(@tmp) < 1) { return ('no data',undef); @@ -913,7 +974,7 @@ sub update_student_data { my $num_parameters = 0; my $store_performance_command = 'INSERT INTO '.$performance_table. ' VALUES '."\n"; - return 'error' if (! defined($dbh)); + return ('error',undef) if (! defined($dbh)); while (my ($current_symb,$param_hash) = each(%student_data)) { # # make sure the symb is set up properly @@ -945,12 +1006,12 @@ sub update_student_data { my $awarddetail = $param_hash->{'resource.'.$part.'.awarddetail'}; my $timestamp = $param_hash->{'timestamp'}; # - $solved = '' if (! defined($awarded)); + $solved = '' if (! defined($solved)); $tries = '' if (! defined($tries)); $awarded = '' if (! defined($awarded)); $award = '' if (! defined($award)); $awarddetail = '' if (! defined($awarddetail)); - $newstring = "('".join("','",$symb_id,$student_id,$part_id, + $newstring = "('".join("','",$symb_id,$student_id,$part_id,$part, $solved,$tries,$awarded,$award, $awarddetail,$timestamp)."'),\n"; $store_performance_command .= $newstring; @@ -967,14 +1028,14 @@ sub update_student_data { &Apache::lonnet::logthis(' bigass insert error:'.$dbh->errstr()); &Apache::lonnet::logthis('command = '.$store_parameters_command); $returnstatus = 'error: unable to insert parameters into database'; - return $returnstatus,\%student_data; + return ($returnstatus,\%student_data); } $dbh->do($store_performance_command); if ($dbh->err()) { &Apache::lonnet::logthis(' bigass insert error:'.$dbh->errstr()); &Apache::lonnet::logthis('command = '.$store_performance_command); $returnstatus = 'error: unable to insert performance into database'; - return $returnstatus,\%student_data; + return ($returnstatus,\%student_data); } $elapsed += Time::HiRes::time - $start; # @@ -1030,7 +1091,7 @@ sub ensure_current_data { !$found_student || !$found_part || !$found_performance || !$found_parameters) { if (&init_dbs($courseid)) { - return 'error'; + return ('error',undef); } } # @@ -1094,12 +1155,12 @@ sub get_student_data_from_performance_ca # my $dbh = &Apache::lonmysql::get_dbh(); my $request = "SELECT ". - "d.symb,c.part,a.solved,a.tries,a.awarded,a.award,a.awarddetail,". + "d.symb,a.part,a.solved,a.tries,a.awarded,a.award,a.awarddetail,". "a.timestamp "; if (defined($student)) { $request .= "FROM $student_table AS b ". "LEFT JOIN $performance_table AS a ON b.student_id=a.student_id ". - "LEFT JOIN $part_table AS c ON c.part_id = a.part_id ". +# "LEFT JOIN $part_table AS c ON c.part_id = a.part_id ". "LEFT JOIN $symb_table AS d ON d.symb_id = a.symb_id ". "WHERE student='$student'"; if (defined($symb) && $symb ne '') { @@ -1108,7 +1169,7 @@ sub get_student_data_from_performance_ca } elsif (defined($symb) && $symb ne '') { $request .= "FROM $symb_table as d ". "LEFT JOIN $performance_table AS a ON d.symb_id=a.symb_id ". - "LEFT JOIN $part_table AS c ON c.part_id = a.part_id ". +# "LEFT JOIN $part_table AS c ON c.part_id = a.part_id ". "LEFT JOIN $student_table AS b ON b.student_id = a.student_id ". "WHERE symb='".$dbh->quote($symb)."'"; } @@ -1134,6 +1195,33 @@ sub get_student_data_from_performance_ca $studentdata->{$symb}->{$base.'.awarddetail'} = $awarddetail; $studentdata->{$symb}->{'timestamp'} = $time if (defined($time) && $time ne ''); } + ## Get misc parameters + $request = 'SELECT c.symb,a.parameter,a.value '. + "FROM $student_table AS b ". + "LEFT JOIN $parameters_table AS a ON b.student_id=a.student_id ". + "LEFT JOIN $symb_table AS c ON c.symb_id = a.symb_id ". + "WHERE student='$student'"; + if (defined($symb) && $symb ne '') { + $request .= " AND c.symb=".$dbh->quote($symb); + } + $sth = $dbh->prepare($request); + $sth->execute(); + if ($sth->err()) { + &Apache::lonnet::logthis("Unable to execute MySQL request:"); + &Apache::lonnet::logthis("\n".$request."\n"); + &Apache::lonnet::logthis("error is:".$sth->errstr()); + if (defined($symb) && $symb ne '') { + $studentdata = $studentdata->{$symb}; + } + return $studentdata; + } + # + foreach my $row (@{$sth->fetchall_arrayref}) { + $rows_retrieved++; + my ($symb,$parameter,$value) = (@$row); + $studentdata->{$symb}->{$parameter} = $value; + } + # if (defined($symb) && $symb ne '') { $studentdata = $studentdata->{$symb}; } @@ -1186,19 +1274,24 @@ sub get_current_state { return () if (! defined($sname) || ! defined($sdom)); # my ($status,$data) = &ensure_current_data($sname,$sdom,$courseid); - &Apache::lonnet::logthis - ('sname = '.$sname. - ' domain = '.$sdom. - ' status = '.$status. - ' data is '.(defined($data)?'defined':'undefined')); - # - if (defined($data)) { - if (defined($symb)) { - return %{$data->{$symb}}; - } else { - return %$data; - } - } elsif ($status eq 'no data') { +# &Apache::lonnet::logthis +# ('sname = '.$sname. +# ' domain = '.$sdom. +# ' status = '.$status. +# ' data is '.(defined($data)?'defined':'undefined')); +# while (my ($symb,$hash) = each(%$data)) { +# &Apache::lonnet::logthis($symb."\n----------------------------------"); +# while (my ($key,$value) = each (%$hash)) { +# &Apache::lonnet::logthis(" ".$key." = ".$value); +# } +# } + # + if (defined($data) && defined($symb) && ref($data->{$symb})) { + return %{$data->{$symb}}; + } elsif (defined($data) && ! defined($symb) && ref($data)) { + return %$data; + } + if ($status eq 'no data') { return (); } else { if ($status ne 'okay' && $status ne '') { @@ -1339,6 +1432,25 @@ sub get_problem_statistics { } # $dbh->do('DROP TABLE '.$stats_table); # May return an error + # + # Store in metadata + # + if ($num) { + my %storestats=(); + + my $urlres=(split(/\_\_\_/,$symb))[2]; + + $storestats{$courseid.'___'.$urlres.'___timestamp'}=time; + $storestats{$courseid.'___'.$urlres.'___stdno'}=$num; + $storestats{$courseid.'___'.$urlres.'___avetries'}=$mean; + $storestats{$courseid.'___'.$urlres.'___difficulty'}=$DegOfDiff; + + $urlres=~/^(\w+)\/(\w+)/; + &Apache::lonnet::put('nohist_resevaldata',\%storestats,$1,$2); + } + # + # Return result + # return { num_students => $num, tries => $tries, max_tries => $mod, @@ -1348,7 +1460,7 @@ sub get_problem_statistics { num_solved => $Solved, num_override => $solved, per_wrong => $wrongpercent, - deg_of_diff => $DegOfDiff } + deg_of_diff => $DegOfDiff }; } sub execute_SQL_request {