--- loncom/interface/loncoursedata.pm 2003/10/24 13:34:45 1.106 +++ loncom/interface/loncoursedata.pm 2004/04/30 20:09:18 1.112.2.2 @@ -1,6 +1,6 @@ # The LearningOnline Network with CAPA # -# $Id: loncoursedata.pm,v 1.106 2003/10/24 13:34:45 matthew Exp $ +# $Id: loncoursedata.pm,v 1.112.2.2 2004/04/30 20:09:18 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -73,8 +73,6 @@ and/or itself. =item &get_sequence_assessment_data() -AT THIS TIME THE USE OF THIS FUNCTION IS *NOT* RECOMMENDED - Use lonnavmaps to build a data structure describing the order and assessment contents of each sequence in the current course. @@ -190,6 +188,10 @@ sub get_sequence_assessment_data { $title =~ s/\:/\&\#058;/g; $symb = $curRes->symb(); $src = $curRes->src(); + # Grab the filename if there is not title available + if (! defined($title) || $title eq '') { + ($title) = ($src=~ m:/([^/]*)$:); + } my $parts = $curRes->parts(); my %partdata; foreach my $part (@$parts) { @@ -579,7 +581,7 @@ sub init_dbs { restrictions => 'NOT NULL', auto_inc => 'yes', }, { name => 'part', - type => 'VARCHAR(100)', + type => 'VARCHAR(100) BINARY', restrictions => 'NOT NULL'}, ], 'PRIMARY KEY' => ['part (100)'], @@ -594,10 +596,10 @@ sub init_dbs { restrictions => 'NOT NULL', auto_inc => 'yes', }, { name => 'student', - type => 'VARCHAR(100)', + type => 'VARCHAR(100) BINARY', restrictions => 'NOT NULL'}, { name => 'classification', - type => 'varchar(100)', }, + type => 'varchar(100) BINARY', }, ], 'PRIMARY KEY' => ['student (100)'], 'KEY' => [{ columns => ['student_id']},], @@ -614,9 +616,9 @@ sub init_dbs { { name => 'fullupdatetime', type => 'INT UNSIGNED'}, { name => 'section', - type => 'VARCHAR(100)'}, + type => 'VARCHAR(100) BINARY'}, { name => 'classification', - type => 'VARCHAR(100)', }, + type => 'VARCHAR(100) BINARY', }, ], 'PRIMARY KEY' => ['student_id'], }; @@ -634,7 +636,7 @@ sub init_dbs { type => 'MEDIUMINT UNSIGNED', restrictions => 'NOT NULL' }, { name => 'part', - type => 'VARCHAR(100)', + type => 'VARCHAR(100) BINARY', restrictions => 'NOT NULL'}, { name => 'solved', type => 'TINYTEXT' }, @@ -714,7 +716,7 @@ sub init_dbs { { name => 'awarddetail', type => 'TINYTEXT' }, # { name => 'message', -# type => 'CHAR' }, +# type => 'CHAR BINARY' }, { name => 'response_specific', type => 'TINYTEXT' }, { name => 'response_specific_value', @@ -1223,11 +1225,7 @@ sub update_full_student_data { # However, there is one wrinkle: submissions which end in # and odd number of '\' cause insert errors to occur. # Best trap this somehow... - $value =~ s/\'/\\\'/g; - my ($offensive_string) = ($value =~ /(\\+)$/); - if (length($offensive_string) % 2) { - $value =~ s/\\$/\\\\/; - } + $value = $dbh->quote($value); } if ($field eq 'submissiongrading' || $field eq 'molecule') { @@ -1276,13 +1274,21 @@ sub update_full_student_data { while (my ($part_id,$hash2) = each (%$hash1)) { while (my ($resp_id,$hash3) = each (%$hash2)) { while (my ($transaction,$data) = each (%$hash3)) { - $store_command .= "('".join("','",$symb_id,$part_id, - $resp_id,$student_id, - $transaction, - $data->{'awarddetail'}, - $data->{'response_specific'}, - $data->{'response_specific_value'}, - $data->{'submission'})."'),"; + my $submission = $data->{'submission'}; + # We have to be careful with user supplied input. + # most of the time we are okay because it is escaped. + # However, there is one wrinkle: submissions which end in + # and odd number of '\' cause insert errors to occur. + # Best trap this somehow... + $submission = $dbh->quote($submission); + $store_command .= "('". + join("','",$symb_id,$part_id, + $resp_id,$student_id, + $transaction, + $data->{'awarddetail'}, + $data->{'response_specific'}, + $data->{'response_specific_value'}). + "',".$submission."),"; $store_rows++; } } @@ -1889,21 +1895,10 @@ sub get_problem_statistics { my $dbh = &Apache::lonmysql::get_dbh(); return undef if (! defined($dbh)); # - # A) Number of Students attempting problem - # B) Total number of tries of students attempting problem - # C) Mod (largest number of tries for solving the problem) - # D) Mean (average number of tries for solving the problem) - # E) Number of students to solve the problem - # F) Number of students to solve the problem by override - # G) Number of students unable to solve the problem - # H) Degree of difficulty : 1-(E+F)/B - # I) Standard deviation of number of tries - # J) Skew of tries: sqrt(sum(Xi-D)^3)/A - # $dbh->do('DROP TABLE '.$stats_table); # May return an error my $request = 'CREATE TEMPORARY TABLE '.$stats_table. - ' SELECT student_id,solved,award,tries FROM '.$performance_table. + ' SELECT student_id,solved,award,awarded,tries FROM '.$performance_table. ' WHERE symb_id='.$symb_id.' AND part_id='.$part_id; if (defined($students)) { $request .= ' AND ('. @@ -1915,16 +1910,22 @@ sub get_problem_statistics { } # &Apache::lonnet::logthis($request); $dbh->do($request); +# &Apache::lonnet::logthis('request = '.$/.$request); + $request = 'SELECT COUNT(*),SUM(tries),MAX(tries),AVG(tries),STD(tries) '. + 'FROM '.$stats_table; my ($num,$tries,$mod,$mean,$STD) = &execute_SQL_request - ($dbh, - 'SELECT COUNT(*),SUM(tries),MAX(tries),AVG(tries),STD(tries) FROM '. - $stats_table); - my ($Solved) = &execute_SQL_request($dbh,'SELECT COUNT(tries) FROM '. - $stats_table. - " WHERE solved='correct_by_student' OR solved='correct_by_scantron'"); - my ($solved) = &execute_SQL_request($dbh,'SELECT COUNT(tries) FROM '. - $stats_table. - " WHERE solved='correct_by_override'"); + ($dbh,$request); +# &Apache::lonnet::logthis('request = '.$/.$request); + $request = 'SELECT SUM(awarded) FROM '.$stats_table; + my ($Solved) = &execute_SQL_request($dbh,$request); +# &Apache::lonnet::logthis('request = '.$/.$request); + $request = 'SELECT SUM(awarded) FROM '.$stats_table. + " WHERE solved='correct_by_override'"; +# &Apache::lonnet::logthis('request = '.$/.$request); + my ($solved) = &execute_SQL_request($dbh,$request); +# $Solved = int($Solved); +# $solved = int($solved); + # $num = 0 if (! defined($num)); $tries = 0 if (! defined($tries)); $mod = 0 if (! defined($mod)); @@ -1944,7 +1945,7 @@ sub get_problem_statistics { $wrongpercent=int(10*100*($num-$Solved+$solved)/$num)/10; } # - $dbh->do('DROP TABLE '.$stats_table); # May return an error +# $dbh->do('DROP TABLE '.$stats_table); # May return an error # # Store in metadata # @@ -2018,7 +2019,15 @@ sub get_student_data { } } -sub get_optionresponse_data { +sub RD_student_id { return 0; } +sub RD_awarddetail { return 1; } +sub RD_response_eval { return 2; } +sub RD_submission { return 3; } +sub RD_timestamp { return 4; } +sub RD_tries { return 5; } +sub RD_sname { return 6; } + +sub get_response_data { my ($students,$symb,$response,$courseid) = @_; return undef if (! defined($symb) || ! defined($response)); @@ -2032,7 +2041,7 @@ sub get_optionresponse_data { return undef if (! defined($dbh)); my $request = 'SELECT '. 'a.student_id, a.awarddetail, a.response_specific_value, '. - 'a.submission, b.timestamp, c.tries '. + 'a.submission, b.timestamp, c.tries, d.student '. 'FROM '.$fulldump_response_table.' AS a '. 'LEFT JOIN '.$fulldump_timestamp_table.' AS b '. 'ON a.symb_id=b.symb_id AND a.student_id=b.student_id AND '. @@ -2040,6 +2049,8 @@ sub get_optionresponse_data { 'LEFT JOIN '.$fulldump_part_table.' AS c '. 'ON a.symb_id=c.symb_id AND a.student_id=c.student_id AND '. 'a.part_id=c.part_id AND a.transaction = c.transaction '. + 'LEFT JOIN '.$student_table.' AS d '. + 'ON a.student_id=d.student_id '. 'WHERE '. 'a.symb_id='.$symb_id.' AND a.response_id='.$response_id; if (defined($students)) { @@ -2060,30 +2071,39 @@ sub get_optionresponse_data { } my $dataset = $sth->fetchall_arrayref(); if (ref($dataset) eq 'ARRAY' && scalar(@$dataset)>0) { + # Clear the \'s from around the submission + for (my $i =0;$i[$i]->[3] =~ s/(\'$|^\')//g; + } return $dataset; } } +sub RT_student_id { return 0; } +sub RT_awarded { return 1; } +sub RT_tries { return 2; } +sub RT_timestamp { return 3; } + sub get_response_time_data { - my ($students,$symb,$response,$courseid) = @_; + my ($students,$symb,$part,$courseid) = @_; return undef if (! defined($symb) || - ! defined($response)); + ! defined($part)); $courseid = $ENV{'request.course.id'} if (! defined($courseid)); # &setup_table_names($courseid); my $symb_id = &get_symb_id($symb); - my $response_id = &get_part_id($response); + my $part_id = &get_part_id($part); # my $dbh = &Apache::lonmysql::get_dbh(); return undef if (! defined($dbh)); my $request = 'SELECT '. - 'a.student_id, a.awarddetail, b.timestamp '. - 'FROM '.$fulldump_response_table.' AS a '. + '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 '. 'WHERE '. - 'a.symb_id='.$symb_id.' AND a.response_id='.$response_id; + 'a.symb_id='.$symb_id.' AND a.part_id='.$part_id; if (defined($students)) { $request .= ' AND ('. join(' OR ', map {'a.student_id='. @@ -2207,7 +2227,7 @@ $ENV{'course.'.$cid.'.domain'}, and $ENV Returns a reference to a hash which contains: keys '$sname:$sdom' - values [$sdom,$sname,$end,$start,$id,$section,$fullname,$status] + values [$sdom,$sname,$end,$start,$id,$section,$fullname,$status,$type] The constant values CL_SDOM, CL_SNAME, CL_END, etc. can be used as indices into the returned list to future-proof clients against @@ -2226,6 +2246,7 @@ sub CL_ID { return 4; } sub CL_SECTION { return 5; } sub CL_FULLNAME { return 6; } sub CL_STATUS { return 7; } +sub CL_TYPE { return 8; } sub get_classlist { my ($cid,$cdom,$cnum) = @_; @@ -2242,9 +2263,9 @@ sub get_classlist { } my ($sname,$sdom) = split(/:/,$student); my @Values = split(/:/,$info); - my ($end,$start,$id,$section,$fullname); + my ($end,$start,$id,$section,$fullname,$type); if (@Values > 2) { - ($end,$start,$id,$section,$fullname) = @Values; + ($end,$start,$id,$section,$fullname,$type) = @Values; } else { # We have to get the data ourselves ($end,$start) = @Values; $section = &Apache::lonnet::getsection($sdom,$sname,$cid); @@ -2281,11 +2302,11 @@ sub get_classlist { $status='Active'; } $classlist{$student} = - [$sdom,$sname,$end,$start,$id,$section,$fullname,$status]; + [$sdom,$sname,$end,$start,$id,$section,$fullname,$status,$type]; } if (wantarray()) { return (\%classlist,['domain','username','end','start','id', - 'section','fullname','status']); + 'section','fullname','status','type']); } else { return \%classlist; }