version 1.95, 2003/09/30 15:45:57
|
version 1.117, 2004/02/17 19:56:30
|
Line 73 and/or itself.
|
Line 73 and/or itself.
|
|
|
=item &get_sequence_assessment_data() |
=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 |
Use lonnavmaps to build a data structure describing the order and |
assessment contents of each sequence in the current course. |
assessment contents of each sequence in the current course. |
|
|
Line 190 sub get_sequence_assessment_data {
|
Line 188 sub get_sequence_assessment_data {
|
$title =~ s/\:/\&\#058;/g; |
$title =~ s/\:/\&\#058;/g; |
$symb = $curRes->symb(); |
$symb = $curRes->symb(); |
$src = $curRes->src(); |
$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 $parts = $curRes->parts(); |
my %partdata; |
my %partdata; |
foreach my $part (@$parts) { |
foreach my $part (@$parts) { |
Line 399 characters) and a KEY on 'part_id'.
|
Line 401 characters) and a KEY on 'part_id'.
|
|
|
=item $student_table |
=item $student_table |
|
|
The student_table has two columns. The first is a 'student_id' and the second |
The student_table has 7 columns. The first is a 'student_id' assigned by |
is the text description of the 'student' (typically username:domain) (less |
MySQL. The second is 'student' which is username:domain. The third through |
than 100 characters). The 'student_id' is automatically generated by MySQL. |
fifth are 'section', 'status' (enrollment status), and 'classification' |
The use of the name 'student_id' is loaded, I know, but this ID is used ONLY |
(to be used in the future). The sixth and seventh ('updatetime' and |
internally to the MySQL database and is not the same as the students ID |
'fullupdatetime') contain the time of last update and full update of student |
(stored in the students environment). This table has its PRIMARY KEY on the |
data. This table has its PRIMARY KEY on the 'student_id' column and is indexed |
'student' (100 characters). |
on 'student', 'section', and 'status'. |
|
|
=item $studentdata_table |
|
|
|
The studentdata_table has four columns: 'student_id' (the unique id of |
|
the student), 'updatetime' (the time the students data was last updated), |
|
'fullupdatetime' (the time the students full data was last updated), |
|
'section', and 'classification'( the students current classification). |
|
This table has its PRIMARY KEY on 'student_id'. |
|
|
|
=back |
=back |
|
|
Line 519 my $current_course ='';
|
Line 513 my $current_course ='';
|
my $symb_table; |
my $symb_table; |
my $part_table; |
my $part_table; |
my $student_table; |
my $student_table; |
my $studentdata_table; |
|
my $performance_table; |
my $performance_table; |
my $parameters_table; |
my $parameters_table; |
my $fulldump_response_table; |
my $fulldump_response_table; |
Line 595 sub init_dbs {
|
Line 588 sub init_dbs {
|
auto_inc => 'yes', }, |
auto_inc => 'yes', }, |
{ name => 'student', |
{ name => 'student', |
type => 'VARCHAR(100)', |
type => 'VARCHAR(100)', |
|
restrictions => 'NOT NULL UNIQUE'}, |
|
{ name => 'section', |
|
type => 'VARCHAR(100)', |
|
restrictions => 'NOT NULL'}, |
|
{ name => 'status', |
|
type => 'VARCHAR(15)', |
restrictions => 'NOT NULL'}, |
restrictions => 'NOT NULL'}, |
{ name => 'classification', |
{ name => 'classification', |
type => 'varchar(100)', }, |
type => 'varchar(100)', }, |
], |
|
'PRIMARY KEY' => ['student (100)'], |
|
'KEY' => [{ columns => ['student_id']},], |
|
}; |
|
# |
|
my $studentdata_table_def = { |
|
id => $studentdata_table, |
|
permanent => 'no', |
|
columns => [{ name => 'student_id', |
|
type => 'MEDIUMINT UNSIGNED', |
|
restrictions => 'NOT NULL UNIQUE',}, |
|
{ name => 'updatetime', |
{ name => 'updatetime', |
type => 'INT UNSIGNED'}, |
type => 'INT UNSIGNED'}, |
{ name => 'fullupdatetime', |
{ name => 'fullupdatetime', |
type => 'INT UNSIGNED'}, |
type => 'INT UNSIGNED'}, |
{ name => 'section', |
|
type => 'VARCHAR(100)'}, |
|
{ name => 'classification', |
|
type => 'VARCHAR(100)', }, |
|
], |
], |
'PRIMARY KEY' => ['student_id'], |
'PRIMARY KEY' => ['student_id'], |
|
'KEY' => [{ columns => ['student (100)', |
|
'section (100)', |
|
'status (15)',]},], |
}; |
}; |
# |
# |
my $performance_table_def = { |
my $performance_table_def = { |
Line 711 sub init_dbs {
|
Line 698 sub init_dbs {
|
{ name => 'transaction', |
{ name => 'transaction', |
type => 'MEDIUMINT UNSIGNED', |
type => 'MEDIUMINT UNSIGNED', |
restrictions => 'NOT NULL' }, |
restrictions => 'NOT NULL' }, |
{ name => 'tries', |
|
type => 'SMALLINT UNSIGNED', |
|
restrictions => 'NOT NULL' }, |
|
{ name => 'awarddetail', |
{ name => 'awarddetail', |
type => 'TINYTEXT' }, |
type => 'TINYTEXT' }, |
# { name => 'message', |
# { name => 'message', |
Line 799 sub init_dbs {
|
Line 783 sub init_dbs {
|
return 3; |
return 3; |
} |
} |
# |
# |
$tableid = &Apache::lonmysql::create_table($studentdata_table_def); |
|
if (! defined($tableid)) { |
|
&Apache::lonnet::logthis("error creating studentdata_table: ". |
|
&Apache::lonmysql::get_error()); |
|
return 4; |
|
} |
|
# |
|
$tableid = &Apache::lonmysql::create_table($performance_table_def); |
$tableid = &Apache::lonmysql::create_table($performance_table_def); |
if (! defined($tableid)) { |
if (! defined($tableid)) { |
&Apache::lonnet::logthis("error creating preformance_table: ". |
&Apache::lonnet::logthis("error creating preformance_table: ". |
Line 1042 sub get_student_id {
|
Line 1019 sub get_student_id {
|
$have_read_student_table = 1; |
$have_read_student_table = 1; |
} |
} |
if (! exists($ids_by_student{$student})) { |
if (! exists($ids_by_student{$student})) { |
&Apache::lonmysql::store_row($student_table,[undef,$student,undef]); |
&populate_student_table(); |
undef(%ids_by_student); |
undef(%ids_by_student); |
|
undef(%students_by_id); |
my @Result = &Apache::lonmysql::get_rows($student_table); |
my @Result = &Apache::lonmysql::get_rows($student_table); |
foreach (@Result) { |
foreach (@Result) { |
$ids_by_student{$_->[1]}=$_->[0]; |
$ids_by_student{$_->[1]}=$_->[0]; |
Line 1067 sub get_student {
|
Line 1045 sub get_student {
|
return undef; # error |
return undef; # error |
} |
} |
|
|
|
sub populate_student_table { |
|
my ($courseid) = @_; |
|
if (! defined($courseid)) { |
|
$courseid = $ENV{'request.course.id'}; |
|
} |
|
# |
|
&setup_table_names($courseid); |
|
my $dbh = &Apache::lonmysql::get_dbh(); |
|
my $request = 'INSERT IGNORE INTO '.$student_table. |
|
"(student,section,status) VALUES "; |
|
my $classlist = &get_classlist($courseid); |
|
my $student_count=0; |
|
while (my ($student,$data) = each %$classlist) { |
|
my ($section,$status) = ($data->[&CL_SECTION()], |
|
$data->[&CL_STATUS()]); |
|
if ($section eq '' || $section =~ /^\s*$/) { |
|
$section = 'none'; |
|
} |
|
$request .= "('".$student."','".$section."','".$status."'),"; |
|
$student_count++; |
|
} |
|
return if ($student_count == 0); |
|
chop($request); |
|
$dbh->do($request); |
|
if ($dbh->err()) { |
|
&Apache::lonnet::logthis("error ".$dbh->errstr(). |
|
" occured executing \n". |
|
$request); |
|
} |
|
return; |
|
} |
|
|
|
|
|
################################################ |
|
################################################ |
|
|
|
=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); |
|
} |
|
|
|
|
################################################ |
################################################ |
################################################ |
################################################ |
|
|
Line 1095 a description of the error.
|
Line 1136 a description of the error.
|
Once the "fulldump" tables are updated, the tables used for chart and |
Once the "fulldump" tables are updated, the tables used for chart and |
spreadsheet (which hold only the current state of the student on their |
spreadsheet (which hold only the current state of the student on their |
homework, not historical data) are updated. If all updates have occured |
homework, not historical data) are updated. If all updates have occured |
successfully, the studentdata table is updated to reflect the time of the |
successfully, $student_table is updated to reflect the time of the update. |
update. |
|
|
|
Notice we do not insert the data and immediately query it. This means it |
Notice we do not insert the data and immediately query it. This means it |
is possible for there to be data returned this first time that is not |
is possible for there to be data returned this first time that is not |
Line 1149 sub update_full_student_data {
|
Line 1189 sub update_full_student_data {
|
# We can deal with 'timestamp' right away |
# We can deal with 'timestamp' right away |
my @timestamp_storage = ($symb_id,$student_id, |
my @timestamp_storage = ($symb_id,$student_id, |
$transaction,$value); |
$transaction,$value); |
my $store_command = 'INSERT INTO '.$fulldump_timestamp_table. |
my $store_command = 'INSERT IGNORE INTO '.$fulldump_timestamp_table. |
" VALUES ('".join("','",@timestamp_storage)."');"; |
" VALUES ('".join("','",@timestamp_storage)."');"; |
$dbh->do($store_command); |
$dbh->do($store_command); |
if ($dbh->err()) { |
if ($dbh->err()) { |
Line 1185 sub update_full_student_data {
|
Line 1225 sub update_full_student_data {
|
} |
} |
# deal with response specific data |
# deal with response specific data |
if (defined($resp_id) && |
if (defined($resp_id) && |
$field =~ /^(tries| |
$field =~ /^(awarddetail| |
awarddetail| |
|
submission| |
submission| |
submissiongrading| |
submissiongrading| |
molecule)$/x) { |
molecule)$/x) { |
Line 1196 sub update_full_student_data {
|
Line 1235 sub update_full_student_data {
|
# However, there is one wrinkle: submissions which end in |
# However, there is one wrinkle: submissions which end in |
# and odd number of '\' cause insert errors to occur. |
# and odd number of '\' cause insert errors to occur. |
# Best trap this somehow... |
# Best trap this somehow... |
my ($offensive_string) = ($value =~ /(\\+)$/); |
$value = $dbh->quote($value); |
if (length($offensive_string) % 2) { |
|
$value =~ s/\\$/\\\\/; |
|
} |
|
} |
} |
if ($field eq 'submissiongrading' || |
if ($field eq 'submissiongrading' || |
$field eq 'molecule') { |
$field eq 'molecule') { |
Line 1213 sub update_full_student_data {
|
Line 1249 sub update_full_student_data {
|
} |
} |
## |
## |
## Store the part data |
## Store the part data |
my $store_command = 'INSERT INTO '.$fulldump_part_table. |
my $store_command = 'INSERT IGNORE INTO '.$fulldump_part_table. |
' VALUES '."\n"; |
' VALUES '."\n"; |
my $store_rows = 0; |
my $store_rows = 0; |
while (my ($symb_id,$hash1) = each (%$partdata)) { |
while (my ($symb_id,$hash1) = each (%$partdata)) { |
Line 1241 sub update_full_student_data {
|
Line 1277 sub update_full_student_data {
|
} |
} |
## |
## |
## Store the response data |
## Store the response data |
$store_command = 'INSERT INTO '.$fulldump_response_table. |
$store_command = 'INSERT IGNORE INTO '.$fulldump_response_table. |
' VALUES '."\n"; |
' VALUES '."\n"; |
$store_rows = 0; |
$store_rows = 0; |
while (my ($symb_id,$hash1) = each (%$respdata)) { |
while (my ($symb_id,$hash1) = each (%$respdata)) { |
while (my ($part_id,$hash2) = each (%$hash1)) { |
while (my ($part_id,$hash2) = each (%$hash1)) { |
while (my ($resp_id,$hash3) = each (%$hash2)) { |
while (my ($resp_id,$hash3) = each (%$hash2)) { |
while (my ($transaction,$data) = each (%$hash3)) { |
while (my ($transaction,$data) = each (%$hash3)) { |
$store_command .= "('".join("','",$symb_id,$part_id, |
my $submission = $data->{'submission'}; |
$resp_id,$student_id, |
# We have to be careful with user supplied input. |
$transaction, |
# most of the time we are okay because it is escaped. |
$data->{'tries'}, |
# However, there is one wrinkle: submissions which end in |
$data->{'awarddetail'}, |
# and odd number of '\' cause insert errors to occur. |
$data->{'response_specific'}, |
# Best trap this somehow... |
$data->{'response_specific_value'}, |
$submission = $dbh->quote($submission); |
$data->{'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++; |
$store_rows++; |
} |
} |
} |
} |
Line 1284 sub update_full_student_data {
|
Line 1327 sub update_full_student_data {
|
## |
## |
## Update the students time...... |
## Update the students time...... |
if ($returnstatus eq 'okay') { |
if ($returnstatus eq 'okay') { |
&Apache::lonmysql::replace_row |
&store_updatetime($student_id,$time_of_retrieval,$time_of_retrieval); |
($studentdata_table, |
if ($dbh->err) { |
[$student_id,$time_of_retrieval,$time_of_retrieval,undef,undef]); |
if ($returnstatus eq 'okay') { |
|
$returnstatus = 'error updating student time'; |
|
} else { |
|
$returnstatus = 'error updating student time'; |
|
} |
|
} |
} |
} |
return $returnstatus; |
return $returnstatus; |
} |
} |
Line 1353 sub update_student_data {
|
Line 1401 sub update_student_data {
|
my @Results = &store_student_data($sname,$sdom,$courseid,\%student_data); |
my @Results = &store_student_data($sname,$sdom,$courseid,\%student_data); |
# |
# |
# Set the students update time |
# Set the students update time |
if ($Results[0] !~ /^error/) { |
if ($Results[0] eq 'okay') { |
&Apache::lonmysql::replace_row($studentdata_table, |
&store_updatetime($student_id,$time_of_retrieval,$time_of_retrieval); |
[$student_id,$time_of_retrieval,undef,undef,undef]); |
|
} |
} |
# |
# |
return @Results; |
return @Results; |
} |
} |
|
|
|
sub store_updatetime { |
|
my ($student_id,$updatetime,$fullupdatetime)=@_; |
|
my $values = ''; |
|
if (defined($updatetime)) { |
|
$values = 'updatetime='.$updatetime.' '; |
|
} |
|
if (defined($fullupdatetime)) { |
|
if ($values ne '') { |
|
$values .= ','; |
|
} |
|
$values .= 'fullupdatetime='.$fullupdatetime.' '; |
|
} |
|
return if ($values eq ''); |
|
my $dbh = &Apache::lonmysql::get_dbh(); |
|
my $request = 'UPDATE '.$student_table.' SET '.$values. |
|
' WHERE student_id='.$student_id.' LIMIT 1'; |
|
$dbh->do($request); |
|
} |
|
|
sub store_student_data { |
sub store_student_data { |
my ($sname,$sdom,$courseid,$student_data) = @_; |
my ($sname,$sdom,$courseid,$student_data) = @_; |
# |
# |
Line 1381 sub store_student_data {
|
Line 1447 sub store_student_data {
|
my $starttime = Time::HiRes::time; |
my $starttime = Time::HiRes::time; |
my $elapsed = 0; |
my $elapsed = 0; |
my $rows_stored; |
my $rows_stored; |
my $store_parameters_command = 'INSERT INTO '.$parameters_table. |
my $store_parameters_command = 'INSERT IGNORE INTO '.$parameters_table. |
' VALUES '."\n"; |
' VALUES '."\n"; |
my $num_parameters = 0; |
my $num_parameters = 0; |
my $store_performance_command = 'INSERT INTO '.$performance_table. |
my $store_performance_command = 'INSERT IGNORE INTO '.$performance_table. |
' VALUES '."\n"; |
' VALUES '."\n"; |
return ('error',undef) if (! defined($dbh)); |
return ('error',undef) if (! defined($dbh)); |
while (my ($current_symb,$param_hash) = each(%{$student_data})) { |
while (my ($current_symb,$param_hash) = each(%{$student_data})) { |
Line 1480 sub ensure_tables_are_set_up {
|
Line 1546 sub ensure_tables_are_set_up {
|
# |
# |
# if the tables do not exist, make them |
# if the tables do not exist, make them |
my @CurrentTable = &Apache::lonmysql::tables_in_db(); |
my @CurrentTable = &Apache::lonmysql::tables_in_db(); |
my ($found_symb,$found_student,$found_part,$found_studentdata, |
my ($found_symb,$found_student,$found_part, |
$found_performance,$found_parameters,$found_fulldump_part, |
$found_performance,$found_parameters,$found_fulldump_part, |
$found_fulldump_response,$found_fulldump_timestamp); |
$found_fulldump_response,$found_fulldump_timestamp); |
foreach (@CurrentTable) { |
foreach (@CurrentTable) { |
$found_symb = 1 if ($_ eq $symb_table); |
$found_symb = 1 if ($_ eq $symb_table); |
$found_student = 1 if ($_ eq $student_table); |
$found_student = 1 if ($_ eq $student_table); |
$found_part = 1 if ($_ eq $part_table); |
$found_part = 1 if ($_ eq $part_table); |
$found_studentdata = 1 if ($_ eq $studentdata_table); |
|
$found_performance = 1 if ($_ eq $performance_table); |
$found_performance = 1 if ($_ eq $performance_table); |
$found_parameters = 1 if ($_ eq $parameters_table); |
$found_parameters = 1 if ($_ eq $parameters_table); |
$found_fulldump_part = 1 if ($_ eq $fulldump_part_table); |
$found_fulldump_part = 1 if ($_ eq $fulldump_part_table); |
$found_fulldump_response = 1 if ($_ eq $fulldump_response_table); |
$found_fulldump_response = 1 if ($_ eq $fulldump_response_table); |
$found_fulldump_timestamp = 1 if ($_ eq $fulldump_timestamp_table); |
$found_fulldump_timestamp = 1 if ($_ eq $fulldump_timestamp_table); |
} |
} |
if (!$found_symb || !$found_studentdata || |
if (!$found_symb || |
!$found_student || !$found_part || |
!$found_student || !$found_part || |
!$found_performance || !$found_parameters || |
!$found_performance || !$found_parameters || |
!$found_fulldump_part || !$found_fulldump_response || |
!$found_fulldump_part || !$found_fulldump_response || |
Line 1517 Input: $sname, $sdom, $courseid
|
Line 1582 Input: $sname, $sdom, $courseid
|
Output: $status, $data |
Output: $status, $data |
|
|
This routine ensures the data for a given student is up to date. |
This routine ensures the data for a given student is up to date. |
The $studentdata_table is queried to determine the time of the last update. |
The $student_table is queried to determine the time of the last update. |
If the students data is out of date, &update_student_data() is called. |
If the students data is out of date, &update_student_data() is called. |
The return values from the call to &update_student_data() are returned. |
The return values from the call to &update_student_data() are returned. |
|
|
Line 1539 sub ensure_current_data {
|
Line 1604 sub ensure_current_data {
|
$Apache::lonnet::perlvar{'lonUsersDir'}); |
$Apache::lonnet::perlvar{'lonUsersDir'}); |
# |
# |
my $student_id = &get_student_id($sname,$sdom); |
my $student_id = &get_student_id($sname,$sdom); |
my @Result = &Apache::lonmysql::get_rows($studentdata_table, |
my @Result = &Apache::lonmysql::get_rows($student_table, |
"student_id ='$student_id'"); |
"student_id ='$student_id'"); |
my $data = undef; |
my $data = undef; |
if (@Result) { |
if (@Result) { |
$updatetime = $Result[0]->[1]; |
$updatetime = $Result[0]->[5]; # Ack! This is dumb! |
} |
} |
if ($modifiedtime > $updatetime) { |
if ($modifiedtime > $updatetime) { |
($status,$data) = &update_student_data($sname,$sdom,$courseid); |
($status,$data) = &update_student_data($sname,$sdom,$courseid); |
Line 1564 Output: $status
|
Line 1629 Output: $status
|
|
|
This routine ensures the fulldata (the data from a lonnet::dump, not a |
This routine ensures the fulldata (the data from a lonnet::dump, not a |
lonnet::currentdump) for a given student is up to date. |
lonnet::currentdump) for a given student is up to date. |
The $studentdata_table is queried to determine the time of the last update. |
The $student_table is queried to determine the time of the last update. |
If the students fulldata is out of date, &update_full_student_data() is |
If the students fulldata is out of date, &update_full_student_data() is |
called. |
called. |
|
|
Line 1587 sub ensure_current_full_data {
|
Line 1652 sub ensure_current_full_data {
|
$Apache::lonnet::perlvar{'lonUsersDir'}); |
$Apache::lonnet::perlvar{'lonUsersDir'}); |
# |
# |
my $student_id = &get_student_id($sname,$sdom); |
my $student_id = &get_student_id($sname,$sdom); |
my @Result = &Apache::lonmysql::get_rows($studentdata_table, |
my @Result = &Apache::lonmysql::get_rows($student_table, |
"student_id ='$student_id'"); |
"student_id ='$student_id'"); |
my $updatetime; |
my $updatetime; |
if (@Result && ref($Result[0]) eq 'ARRAY') { |
if (@Result && ref($Result[0]) eq 'ARRAY') { |
$updatetime = $Result[0]->[2]; |
$updatetime = $Result[0]->[6]; |
} |
} |
if (! defined($updatetime) || $modifiedtime > $updatetime) { |
if (! defined($updatetime) || $modifiedtime > $updatetime) { |
$status = &update_full_student_data($sname,$sdom,$courseid); |
$status = &update_full_student_data($sname,$sdom,$courseid); |
Line 1680 sub get_student_data_from_performance_ca
|
Line 1745 sub get_student_data_from_performance_ca
|
$studentdata->{$symb}->{$base.'.awarddetail'} = $awarddetail; |
$studentdata->{$symb}->{$base.'.awarddetail'} = $awarddetail; |
$studentdata->{$symb}->{'timestamp'} = $time if (defined($time) && $time ne ''); |
$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 '') { |
if (defined($symb) && $symb ne '') { |
$studentdata = $studentdata->{$symb}; |
$studentdata = $studentdata->{$symb}; |
} |
} |
Line 1823 able to answer it correctly.
|
Line 1915 able to answer it correctly.
|
################################################ |
################################################ |
################################################ |
################################################ |
sub get_problem_statistics { |
sub get_problem_statistics { |
my ($students,$symb,$part,$courseid) = @_; |
my ($Sections,$status,$symb,$part,$courseid) = @_; |
return if (! defined($symb) || ! defined($part)); |
return if (! defined($symb) || ! defined($part)); |
$courseid = $ENV{'request.course.id'} if (! defined($courseid)); |
$courseid = $ENV{'request.course.id'} if (! defined($courseid)); |
# |
# |
|
&setup_table_names($courseid); |
my $symb_id = &get_symb_id($symb); |
my $symb_id = &get_symb_id($symb); |
my $part_id = &get_part_id($part); |
my $part_id = &get_part_id($part); |
my $stats_table = $courseid.'_problem_stats'; |
my $stats_table = $courseid.'_problem_stats'; |
Line 1834 sub get_problem_statistics {
|
Line 1927 sub get_problem_statistics {
|
my $dbh = &Apache::lonmysql::get_dbh(); |
my $dbh = &Apache::lonmysql::get_dbh(); |
return undef if (! defined($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 |
$dbh->do('DROP TABLE '.$stats_table); # May return an error |
my $request = |
my $request = |
'CREATE TEMPORARY TABLE '.$stats_table. |
'CREATE TEMPORARY TABLE '.$stats_table.' '. |
' SELECT student_id,solved,award,tries FROM '.$performance_table. |
'SELECT a.student_id,a.solved,a.award,a.awarded,a.tries '. |
' WHERE symb_id='.$symb_id.' AND part_id='.$part_id; |
'FROM '.$performance_table.' AS a '; |
if (defined($students)) { |
if ((defined($Sections) && lc($Sections->[0]) ne 'all') || |
|
(defined($status) && lc($status) ne 'any')) { |
|
$request .= 'NATURAL LEFT JOIN '.$student_table.' AS b '; |
|
} |
|
$request .= ' WHERE a.symb_id='.$symb_id.' AND a.part_id='.$part_id; |
|
if (defined($Sections) && lc($Sections->[0]) ne 'all') { |
$request .= ' AND ('. |
$request .= ' AND ('. |
join(' OR ', map {'student_id='. |
join(' OR ', map { "b.section='".$_."'" } @$Sections |
&get_student_id($_->{'username'}, |
|
$_->{'domain'}) |
|
} @$students |
|
).')'; |
).')'; |
} |
} |
# &Apache::lonnet::logthis($request); |
if (defined($status) && lc($status) ne 'any') { |
|
$request .= " AND b.status='".$status."'"; |
|
} |
$dbh->do($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 |
my ($num,$tries,$mod,$mean,$STD) = &execute_SQL_request |
($dbh, |
($dbh,$request); |
'SELECT COUNT(*),SUM(tries),MAX(tries),AVG(tries),STD(tries) FROM '. |
# &Apache::lonnet::logthis('request = '.$/.$request); |
$stats_table); |
$request = 'SELECT SUM(awarded) FROM '.$stats_table; |
my ($Solved) = &execute_SQL_request($dbh,'SELECT COUNT(tries) FROM '. |
my ($Solved) = &execute_SQL_request($dbh,$request); |
$stats_table. |
# &Apache::lonnet::logthis('request = '.$/.$request); |
" WHERE solved='correct_by_student' OR solved='correct_by_scantron'"); |
$request = 'SELECT SUM(awarded) FROM '.$stats_table. |
my ($solved) = &execute_SQL_request($dbh,'SELECT COUNT(tries) FROM '. |
" WHERE solved='correct_by_override'"; |
$stats_table. |
# &Apache::lonnet::logthis('request = '.$/.$request); |
" WHERE solved='correct_by_override'"); |
my ($solved) = &execute_SQL_request($dbh,$request); |
|
# $Solved = int($Solved); |
|
# $solved = int($solved); |
|
# |
$num = 0 if (! defined($num)); |
$num = 0 if (! defined($num)); |
$tries = 0 if (! defined($tries)); |
$tries = 0 if (! defined($tries)); |
$mod = 0 if (! defined($mod)); |
$mod = 0 if (! defined($mod)); |
Line 1889 sub get_problem_statistics {
|
Line 1981 sub get_problem_statistics {
|
$wrongpercent=int(10*100*($num-$Solved+$solved)/$num)/10; |
$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 |
# Store in metadata |
# |
# |
Line 1933 sub execute_SQL_request {
|
Line 2025 sub execute_SQL_request {
|
return (); |
return (); |
} |
} |
|
|
|
sub get_student_data { |
|
my ($students,$courseid) = @_; |
|
$courseid = $ENV{'request.course.id'} if (! defined($courseid)); |
|
&setup_table_names($courseid); |
|
my $dbh = &Apache::lonmysql::get_dbh(); |
|
return undef if (! defined($dbh)); |
|
my $request = 'SELECT '. |
|
'student_id, student '. |
|
'FROM '.$student_table; |
|
if (defined($students)) { |
|
$request .= ' WHERE ('. |
|
join(' OR ', map {'student_id='. |
|
&get_student_id($_->{'username'}, |
|
$_->{'domain'}) |
|
} @$students |
|
).')'; |
|
} |
|
$request.= ' ORDER BY student_id'; |
|
my $sth = $dbh->prepare($request); |
|
$sth->execute(); |
|
if ($dbh->err) { |
|
&Apache::lonnet::logthis('error = '.$dbh->errstr()); |
|
return undef; |
|
} |
|
my $dataset = $sth->fetchall_arrayref(); |
|
if (ref($dataset) eq 'ARRAY' && scalar(@$dataset)>0) { |
|
return $dataset; |
|
} |
|
} |
|
|
|
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)); |
|
$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 $dbh = &Apache::lonmysql::get_dbh(); |
|
return undef if (! defined($dbh)); |
|
my $request = 'SELECT '. |
|
'a.student_id, a.awarddetail, a.response_specific_value, '. |
|
'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 '. |
|
'a.transaction = b.transaction '. |
|
'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)) { |
|
$request .= ' AND ('. |
|
join(' OR ', map {'a.student_id='. |
|
&get_student_id($_->{'username'}, |
|
$_->{'domain'}) |
|
} @$students |
|
).')'; |
|
} |
|
$request .= ' ORDER BY b.timestamp'; |
|
# &Apache::lonnet::logthis("request =\n".$request); |
|
my $sth = $dbh->prepare($request); |
|
$sth->execute(); |
|
if ($dbh->err) { |
|
&Apache::lonnet::logthis('error = '.$dbh->errstr()); |
|
return undef; |
|
} |
|
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<scalar(@$dataset);$i++) { |
|
$dataset->[$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,$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); |
|
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.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.part_id='.$part_id; |
|
if (defined($students)) { |
|
$request .= ' AND ('. |
|
join(' OR ', map {'a.student_id='. |
|
&get_student_id($_->{'username'}, |
|
$_->{'domain'}) |
|
} @$students |
|
).')'; |
|
} |
|
$request .= ' ORDER BY b.timestamp'; |
|
# &Apache::lonnet::logthis("request =\n".$request); |
|
my $sth = $dbh->prepare($request); |
|
$sth->execute(); |
|
if ($dbh->err) { |
|
&Apache::lonnet::logthis('error = '.$dbh->errstr()); |
|
return undef; |
|
} |
|
my $dataset = $sth->fetchall_arrayref(); |
|
if (ref($dataset) eq 'ARRAY' && scalar(@$dataset)>0) { |
|
return $dataset; |
|
} |
|
|
|
} |
|
|
|
################################################ |
|
################################################ |
|
|
|
=pod |
|
|
|
=item &get_student_scores($Sections,$Symbs,$enrollment,$courseid) |
|
|
|
=cut |
|
|
|
################################################ |
|
################################################ |
|
sub get_student_scores { |
|
my ($Sections,$Symbs,$enrollment,$courseid) = @_; |
|
$courseid = $ENV{'request.course.id'} if (! defined($courseid)); |
|
&setup_table_names($courseid); |
|
my $dbh = &Apache::lonmysql::get_dbh(); |
|
return (undef) if (! defined($dbh)); |
|
my $tmptable = $courseid.'_temp_'.time; |
|
# |
|
my $symb_requirements; |
|
if (defined($Symbs) && @$Symbs) { |
|
$symb_requirements = '('. |
|
join(' OR ', map{ "(a.symb_id='".&get_symb_id($_->{'symb'}). |
|
"' AND a.part_id='".&get_part_id($_->{'part'}). |
|
"')" |
|
} @$Symbs).')'; |
|
} |
|
# |
|
my $student_requirements; |
|
if ( (defined($Sections) && $Sections->[0] ne 'all')) { |
|
$student_requirements = '('. |
|
join(' OR ', map { "b.section='".$_."'" } @$Sections |
|
).')'; |
|
} |
|
# |
|
my $enrollment_requirements=undef; |
|
if (defined($enrollment) && $enrollment ne 'Any') { |
|
$enrollment_requirements = "b.status='".$enrollment."'"; |
|
} |
|
## |
|
## |
|
my $request = 'CREATE TEMPORARY TABLE IF NOT EXISTS '.$tmptable. |
|
' SELECT a.student_id,SUM(a.awarded) AS score FROM '. |
|
$performance_table.' AS a '; |
|
if (defined($student_requirements) || defined($enrollment_requirements)) { |
|
$request .= ' NATURAL LEFT JOIN '.$student_table.' AS b '; |
|
} |
|
if (defined($symb_requirements) || |
|
defined($student_requirements) || |
|
defined($enrollment_requirements) ) { |
|
$request .= ' WHERE '; |
|
} |
|
if (defined($symb_requirements)) { |
|
$request .= $symb_requirements.' AND '; |
|
} |
|
if (defined($student_requirements)) { |
|
$request .= $student_requirements.' AND '; |
|
} |
|
if (defined($enrollment_requirements)) { |
|
$request .= $enrollment_requirements.' AND '; |
|
} |
|
$request =~ s/ AND $//; |
|
$request .= ' GROUP BY a.student_id'; |
|
# &Apache::lonnet::logthis("request = \n".$request); |
|
my $sth = $dbh->prepare($request); |
|
$sth->execute(); |
|
if ($dbh->err) { |
|
&Apache::lonnet::logthis('error = '.$dbh->errstr()); |
|
return undef; |
|
} |
|
$request = 'SELECT score,COUNT(*) FROM '.$tmptable.' GROUP BY score'; |
|
# &Apache::lonnet::logthis("request = \n".$request); |
|
$sth = $dbh->prepare($request); |
|
$sth->execute(); |
|
if ($dbh->err) { |
|
&Apache::lonnet::logthis('error = '.$dbh->errstr()); |
|
return undef; |
|
} |
|
my $dataset = $sth->fetchall_arrayref(); |
|
return $dataset; |
|
} |
|
|
################################################ |
################################################ |
################################################ |
################################################ |
Line 1977 sub setup_table_names {
|
Line 2288 sub setup_table_names {
|
$symb_table = $base_id.'_'.'symb'; |
$symb_table = $base_id.'_'.'symb'; |
$part_table = $base_id.'_'.'part'; |
$part_table = $base_id.'_'.'part'; |
$student_table = $base_id.'_'.'student'; |
$student_table = $base_id.'_'.'student'; |
$studentdata_table = $base_id.'_'.'studentdata'; |
|
$performance_table = $base_id.'_'.'performance'; |
$performance_table = $base_id.'_'.'performance'; |
$parameters_table = $base_id.'_'.'parameters'; |
$parameters_table = $base_id.'_'.'parameters'; |
$fulldump_part_table = $base_id.'_'.'partdata'; |
$fulldump_part_table = $base_id.'_'.'partdata'; |
Line 1988 sub setup_table_names {
|
Line 2298 sub setup_table_names {
|
$symb_table, |
$symb_table, |
$part_table, |
$part_table, |
$student_table, |
$student_table, |
$studentdata_table, |
|
$performance_table, |
$performance_table, |
$parameters_table, |
$parameters_table, |
$fulldump_part_table, |
$fulldump_part_table, |
Line 2034 $ENV{'course.'.$cid.'.domain'}, and $ENV
|
Line 2343 $ENV{'course.'.$cid.'.domain'}, and $ENV
|
|
|
Returns a reference to a hash which contains: |
Returns a reference to a hash which contains: |
keys '$sname:$sdom' |
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 |
The constant values CL_SDOM, CL_SNAME, CL_END, etc. can be used |
as indices into the returned list to future-proof clients against |
as indices into the returned list to future-proof clients against |
Line 2053 sub CL_ID { return 4; }
|
Line 2362 sub CL_ID { return 4; }
|
sub CL_SECTION { return 5; } |
sub CL_SECTION { return 5; } |
sub CL_FULLNAME { return 6; } |
sub CL_FULLNAME { return 6; } |
sub CL_STATUS { return 7; } |
sub CL_STATUS { return 7; } |
|
sub CL_TYPE { return 8; } |
|
|
sub get_classlist { |
sub get_classlist { |
my ($cid,$cdom,$cnum) = @_; |
my ($cid,$cdom,$cnum) = @_; |
Line 2069 sub get_classlist {
|
Line 2379 sub get_classlist {
|
} |
} |
my ($sname,$sdom) = split(/:/,$student); |
my ($sname,$sdom) = split(/:/,$student); |
my @Values = split(/:/,$info); |
my @Values = split(/:/,$info); |
my ($end,$start,$id,$section,$fullname); |
my ($end,$start,$id,$section,$fullname,$type); |
if (@Values > 2) { |
if (@Values > 2) { |
($end,$start,$id,$section,$fullname) = @Values; |
($end,$start,$id,$section,$fullname,$type) = @Values; |
} else { # We have to get the data ourselves |
} else { # We have to get the data ourselves |
($end,$start) = @Values; |
($end,$start) = @Values; |
$section = &Apache::lonnet::getsection($sdom,$sname,$cid); |
$section = &Apache::lonnet::getsection($sdom,$sname,$cid); |
Line 2108 sub get_classlist {
|
Line 2418 sub get_classlist {
|
$status='Active'; |
$status='Active'; |
} |
} |
$classlist{$student} = |
$classlist{$student} = |
[$sdom,$sname,$end,$start,$id,$section,$fullname,$status]; |
[$sdom,$sname,$end,$start,$id,$section,$fullname,$status,$type]; |
} |
} |
if (wantarray()) { |
if (wantarray()) { |
return (\%classlist,['domain','username','end','start','id', |
return (\%classlist,['domain','username','end','start','id', |
'section','fullname','status']); |
'section','fullname','status','type']); |
} else { |
} else { |
return \%classlist; |
return \%classlist; |
} |
} |