version 1.65, 2003/03/28 18:14:59
|
version 1.83, 2003/08/07 17:26:44
|
Line 104 sub get_sequence_assessment_data {
|
Line 104 sub get_sequence_assessment_data {
|
my $fn=$ENV{'request.course.fn'}; |
my $fn=$ENV{'request.course.fn'}; |
## |
## |
## use navmaps |
## use navmaps |
my $navmap = Apache::lonnavmaps::navmap->new($fn.".db", |
my $navmap = Apache::lonnavmaps::navmap->new(); |
$fn."_parms.db",1,0); |
|
if (!defined($navmap)) { |
if (!defined($navmap)) { |
return 'Can not open Coursemap'; |
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 $iterator = $navmap->getIterator(undef, undef, undef, 1); |
my $curRes = $iterator->next(); # Top level sequence |
my $curRes = $iterator->next(); # Top level sequence |
## |
## |
Line 118 sub get_sequence_assessment_data {
|
Line 121 sub get_sequence_assessment_data {
|
## resources. This means we have to start out with something to look |
## resources. This means we have to start out with something to look |
## at. |
## at. |
my $title = $ENV{'course.'.$ENV{'request.course.id'}.'.description'}; |
my $title = $ENV{'course.'.$ENV{'request.course.id'}.'.description'}; |
my $symb = 'top'; |
my $symb = $top_level_map->symb(); |
my $src = 'not applicable'; |
my $src = $top_level_map->src(); |
|
my $randompick = $top_level_map->randompick(); |
# |
# |
my @Sequences; |
my @Sequences; |
my @Assessments; |
my @Assessments; |
Line 130 sub get_sequence_assessment_data {
|
Line 134 sub get_sequence_assessment_data {
|
type => 'container', |
type => 'container', |
num_assess => 0, |
num_assess => 0, |
num_assess_parts => 0, |
num_assess_parts => 0, |
contents => [], }; |
contents => [], |
|
randompick => $randompick, |
|
}; |
push (@Sequences,$top); |
push (@Sequences,$top); |
push (@Nested_Sequences, $top); |
push (@Nested_Sequences, $top); |
# |
# |
# We need to keep track of which sequences contain homework problems |
# We need to keep track of which sequences contain homework problems |
# |
# |
|
my $previous_too; |
my $previous; |
my $previous; |
$curRes = $iterator->next(); # BEGIN_MAP |
|
$curRes = $iterator->next(); # The first item in the top level map. |
|
while (scalar(@Nested_Sequences)) { |
while (scalar(@Nested_Sequences)) { |
|
$previous_too = $previous; |
$previous = $curRes; |
$previous = $curRes; |
$curRes = $iterator->next(); |
$curRes = $iterator->next(); |
my $currentmap = $Nested_Sequences[-1]; # Last one on the stack |
my $currentmap = $Nested_Sequences[-1]; # Last one on the stack |
if ($curRes == $iterator->BEGIN_MAP()) { |
if ($curRes == $iterator->BEGIN_MAP()) { |
|
if (! ref($previous)) { |
|
$previous = $previous_too; |
|
} |
|
if (! ref($previous)) { |
|
next; |
|
} |
# get the map itself, instead of BEGIN_MAP |
# get the map itself, instead of BEGIN_MAP |
$title = $previous->title(); |
$title = $previous->title(); |
$symb = $previous->symb(); |
$symb = $previous->symb(); |
$src = $previous->src(); |
$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, |
my $newmap = { title => $title, |
src => $src, |
src => $src, |
symb => $symb, |
symb => $symb, |
type => 'container', |
type => 'container', |
num_assess => 0, |
num_assess => 0, |
|
randompick => $randompick, |
contents => [], |
contents => [], |
}; |
}; |
push (@{$currentmap->{'contents'}},$newmap); # this is permanent |
push (@{$currentmap->{'contents'}},$newmap); # this is permanent |
Line 211 sub LoadDiscussion {
|
Line 229 sub LoadDiscussion {
|
return \%Discuss; |
return \%Discuss; |
} |
} |
|
|
|
################################################ |
|
################################################ |
|
|
|
=pod |
|
|
|
=item &GetUserName(username,userdomain) |
|
|
|
Returns a hash with the following entries: |
|
'firstname', 'middlename', 'lastname', 'generation', and 'fullname' |
|
|
|
'fullname' is the result of &Apache::loncoursedata::ProcessFullName. |
|
|
|
=cut |
|
|
|
################################################ |
|
################################################ |
|
sub GetUserName { |
|
my ($username,$userdomain) = @_; |
|
$username = $ENV{'user.name'} if (! defined($username)); |
|
$userdomain = $ENV{'user.domain'} if (! defined($username)); |
|
my %userenv = &Apache::lonnet::get('environment', |
|
['firstname','middlename','lastname','generation'], |
|
$userdomain,$username); |
|
$userenv{'fullname'} = &ProcessFullName($userenv{'lastname'}, |
|
$userenv{'generation'}, |
|
$userenv{'firstname'}, |
|
$userenv{'middlename'}); |
|
return %userenv; |
|
} |
|
|
|
################################################ |
|
################################################ |
|
|
=pod |
=pod |
|
|
=item &ProcessFullName() |
=item &ProcessFullName() |
Line 221 is Lastname generation, firstname middle
|
Line 272 is Lastname generation, firstname middle
|
|
|
=cut |
=cut |
|
|
|
################################################ |
|
################################################ |
sub ProcessFullName { |
sub ProcessFullName { |
my ($lastname, $generation, $firstname, $middlename)=@_; |
my ($lastname, $generation, $firstname, $middlename)=@_; |
my $Str = ''; |
my $Str = ''; |
Line 422 sub init_dbs {
|
Line 475 sub init_dbs {
|
my $courseid = shift; |
my $courseid = shift; |
&setup_table_names($courseid); |
&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 |
# Note - changes to this table must be reflected in the code that |
# stores the data (calls &Apache::lonmysql::store_row with this table |
# stores the data (calls &Apache::lonmysql::store_row with this table |
# id |
# id |
Line 494 sub init_dbs {
|
Line 554 sub init_dbs {
|
{ name => 'part_id', |
{ name => 'part_id', |
type => 'MEDIUMINT UNSIGNED', |
type => 'MEDIUMINT UNSIGNED', |
restrictions => 'NOT NULL' }, |
restrictions => 'NOT NULL' }, |
|
{ name => 'part', |
|
type => 'VARCHAR(100)', |
|
restrictions => 'NOT NULL'}, |
{ name => 'solved', |
{ name => 'solved', |
type => 'TINYTEXT' }, |
type => 'TINYTEXT' }, |
{ name => 'tries', |
{ name => 'tries', |
Line 581 sub init_dbs {
|
Line 644 sub init_dbs {
|
|
|
=pod |
=pod |
|
|
|
=item &delete_caches() |
|
|
|
=cut |
|
|
|
################################################ |
|
################################################ |
|
sub delete_caches { |
|
my $courseid = shift; |
|
$courseid = $ENV{'request.course.id'} if (! defined($courseid)); |
|
# |
|
&setup_table_names($courseid); |
|
# |
|
my $dbh = &Apache::lonmysql::get_dbh(); |
|
foreach my $table ($symb_table,$part_table,$student_table, |
|
$updatetime_table,$performance_table, |
|
$parameters_table ){ |
|
my $command = 'DROP TABLE '.$table.';'; |
|
$dbh->do($command); |
|
if ($dbh->err) { |
|
&Apache::lonnet::logthis($command.' resulted in error: '.$dbh->errstr); |
|
} |
|
} |
|
return; |
|
} |
|
|
|
################################################ |
|
################################################ |
|
|
|
=pod |
|
|
=item &get_part_id() |
=item &get_part_id() |
|
|
Get the MySQL id of a problem part string. |
Get the MySQL id of a problem part string. |
Line 826 sub update_student_data {
|
Line 919 sub update_student_data {
|
$sname.':'.$sdom.' in course '.$courseid. |
$sname.':'.$sdom.' in course '.$courseid. |
':'.$tmp[0]); |
':'.$tmp[0]); |
$returnstatus = 'error getting data'; |
$returnstatus = 'error getting data'; |
return $returnstatus; |
return ($returnstatus,undef); |
} |
} |
if (scalar(@tmp) < 1) { |
if (scalar(@tmp) < 1) { |
return ('no data',undef); |
return ('no data',undef); |
Line 850 sub update_student_data {
|
Line 943 sub update_student_data {
|
my $num_parameters = 0; |
my $num_parameters = 0; |
my $store_performance_command = 'INSERT INTO '.$performance_table. |
my $store_performance_command = 'INSERT INTO '.$performance_table. |
' VALUES '."\n"; |
' VALUES '."\n"; |
return 'error' 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)) { |
# |
# |
# make sure the symb is set up properly |
# make sure the symb is set up properly |
Line 862 sub update_student_data {
|
Line 955 sub update_student_data {
|
if ($parameter !~ /(timestamp|resource\.(.*)\.(solved|tries|awarded|award|awarddetail|previous))/) { |
if ($parameter !~ /(timestamp|resource\.(.*)\.(solved|tries|awarded|award|awarddetail|previous))/) { |
$newstring = "('".join("','", |
$newstring = "('".join("','", |
$symb_id,$student_id, |
$symb_id,$student_id, |
$parameter,$value)."'),\n"; |
$parameter)."',". |
|
$dbh->quote($value)."),\n"; |
$num_parameters ++; |
$num_parameters ++; |
if ($newstring !~ /''/) { |
if ($newstring !~ /''/) { |
$store_parameters_command .= $newstring; |
$store_parameters_command .= $newstring; |
Line 881 sub update_student_data {
|
Line 975 sub update_student_data {
|
my $awarddetail = $param_hash->{'resource.'.$part.'.awarddetail'}; |
my $awarddetail = $param_hash->{'resource.'.$part.'.awarddetail'}; |
my $timestamp = $param_hash->{'timestamp'}; |
my $timestamp = $param_hash->{'timestamp'}; |
# |
# |
$solved = '' if (! defined($awarded)); |
$solved = '' if (! defined($solved)); |
$tries = '' if (! defined($tries)); |
$tries = '' if (! defined($tries)); |
$awarded = '' if (! defined($awarded)); |
$awarded = '' if (! defined($awarded)); |
$award = '' if (! defined($award)); |
$award = '' if (! defined($award)); |
$awarddetail = '' if (! defined($awarddetail)); |
$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, |
$solved,$tries,$awarded,$award, |
$awarddetail,$timestamp)."'),\n"; |
$awarddetail,$timestamp)."'),\n"; |
$store_performance_command .= $newstring; |
$store_performance_command .= $newstring; |
Line 903 sub update_student_data {
|
Line 997 sub update_student_data {
|
&Apache::lonnet::logthis(' bigass insert error:'.$dbh->errstr()); |
&Apache::lonnet::logthis(' bigass insert error:'.$dbh->errstr()); |
&Apache::lonnet::logthis('command = '.$store_parameters_command); |
&Apache::lonnet::logthis('command = '.$store_parameters_command); |
$returnstatus = 'error: unable to insert parameters into database'; |
$returnstatus = 'error: unable to insert parameters into database'; |
return $returnstatus,\%student_data; |
return ($returnstatus,\%student_data); |
} |
} |
$dbh->do($store_performance_command); |
$dbh->do($store_performance_command); |
if ($dbh->err()) { |
if ($dbh->err()) { |
&Apache::lonnet::logthis(' bigass insert error:'.$dbh->errstr()); |
&Apache::lonnet::logthis(' bigass insert error:'.$dbh->errstr()); |
&Apache::lonnet::logthis('command = '.$store_performance_command); |
&Apache::lonnet::logthis('command = '.$store_performance_command); |
$returnstatus = 'error: unable to insert performance into database'; |
$returnstatus = 'error: unable to insert performance into database'; |
return $returnstatus,\%student_data; |
return ($returnstatus,\%student_data); |
} |
} |
$elapsed += Time::HiRes::time - $start; |
$elapsed += Time::HiRes::time - $start; |
# |
# |
Line 966 sub ensure_current_data {
|
Line 1060 sub ensure_current_data {
|
!$found_student || !$found_part || |
!$found_student || !$found_part || |
!$found_performance || !$found_parameters) { |
!$found_performance || !$found_parameters) { |
if (&init_dbs($courseid)) { |
if (&init_dbs($courseid)) { |
return 'error'; |
return ('error',undef); |
} |
} |
} |
} |
# |
# |
Line 1030 sub get_student_data_from_performance_ca
|
Line 1124 sub get_student_data_from_performance_ca
|
# |
# |
my $dbh = &Apache::lonmysql::get_dbh(); |
my $dbh = &Apache::lonmysql::get_dbh(); |
my $request = "SELECT ". |
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 "; |
"a.timestamp "; |
if (defined($student)) { |
if (defined($student)) { |
$request .= "FROM $student_table AS b ". |
$request .= "FROM $student_table AS b ". |
"LEFT JOIN $performance_table AS a ON b.student_id=a.student_id ". |
"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 ". |
"LEFT JOIN $symb_table AS d ON d.symb_id = a.symb_id ". |
"WHERE student='$student'"; |
"WHERE student='$student'"; |
if (defined($symb) && $symb ne '') { |
if (defined($symb) && $symb ne '') { |
$request .= " AND d.symb='".$dbh->quote($symb)."'"; |
$request .= " AND d.symb=".$dbh->quote($symb); |
} |
} |
} elsif (defined($symb) && $symb ne '') { |
} elsif (defined($symb) && $symb ne '') { |
$request .= "FROM $symb_table as d ". |
$request .= "FROM $symb_table as d ". |
"LEFT JOIN $performance_table AS a ON d.symb_id=a.symb_id ". |
"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 ". |
"LEFT JOIN $student_table AS b ON b.student_id = a.student_id ". |
"WHERE symb='".$dbh->quote($symb)."'"; |
"WHERE symb='".$dbh->quote($symb)."'"; |
} |
} |
Line 1070 sub get_student_data_from_performance_ca
|
Line 1164 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 ''); |
} |
} |
|
if (defined($symb) && $symb ne '') { |
|
$studentdata = $studentdata->{$symb}; |
|
} |
return $studentdata; |
return $studentdata; |
} |
} |
|
|
Line 1119 sub get_current_state {
|
Line 1216 sub get_current_state {
|
return () if (! defined($sname) || ! defined($sdom)); |
return () if (! defined($sname) || ! defined($sdom)); |
# |
# |
my ($status,$data) = &ensure_current_data($sname,$sdom,$courseid); |
my ($status,$data) = &ensure_current_data($sname,$sdom,$courseid); |
# |
# &Apache::lonnet::logthis |
if (defined($data)) { |
# ('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; |
return %$data; |
} elsif ($status eq 'no data') { |
} |
|
if ($status eq 'no data') { |
return (); |
return (); |
} else { |
} else { |
if ($status ne 'okay' && $status ne '') { |
if ($status ne 'okay' && $status ne '') { |
Line 1163 Each hash must contain at least the 'use
|
Line 1274 Each hash must contain at least the 'use
|
|
|
=back |
=back |
|
|
Outputs: See the code for up to date information. |
Outputs: See the code for up to date information. A hash reference is |
|
returned. The hash has the following keys defined: |
|
|
=over 4 |
=over 4 |
|
|
=item $num The number of students attempting the problem |
=item num_students The number of students attempting the problem |
|
|
=item $tries The total number of tries for the students |
=item tries The total number of tries for the students |
|
|
=item $mod The maximum number of tries taken |
=item max_tries The maximum number of tries taken |
|
|
=item $mean The average number of tries |
=item mean_tries The average number of tries |
|
|
=item $Solved The number of students able to solve the problem |
=item num_solved The number of students able to solve the problem |
|
|
|
=item num_override The number of students whose answer is 'correct_by_override' |
|
|
|
=item deg_of_diff The degree of difficulty of the problem |
|
|
|
=item std_tries The standard deviation of the number of tries |
|
|
|
=item skew_tries The skew of the number of tries |
|
|
=item $solved The number of students whose answer is 'correct_by_override' |
=item per_wrong The number of students attempting the problem who were not |
|
able to answer it correctly. |
=item $DegOfDiff The degree of difficulty of the problem |
|
|
|
=item $STD The standard deviation of the number of tries |
|
|
|
=item $SKEW The skew of the number of tries |
|
|
|
=back |
=back |
|
|
Line 1247 sub get_problem_statistics {
|
Line 1362 sub get_problem_statistics {
|
$solved = 0 if (! defined($solved)); |
$solved = 0 if (! defined($solved)); |
# |
# |
my $DegOfDiff = 'nan'; |
my $DegOfDiff = 'nan'; |
$DegOfDiff = 1-($Solved + $solved)/$tries if ($tries>0); |
$DegOfDiff = 1-($Solved)/$tries if ($tries>0); |
|
|
my $SKEW = 'nan'; |
my $SKEW = 'nan'; |
|
my $wrongpercent = 0; |
if ($num > 0) { |
if ($num > 0) { |
($SKEW) = &execute_SQL_request($dbh,'SELECT SQRT(SUM('. |
($SKEW) = &execute_SQL_request($dbh,'SELECT SQRT(SUM('. |
'POWER(tries - '.$STD.',3)'. |
'POWER(tries - '.$STD.',3)'. |
'))/'.$num.' FROM '.$stats_table); |
'))/'.$num.' FROM '.$stats_table); |
|
$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 |
return ($num,$tries,$mod,$mean,$Solved,$solved,$DegOfDiff,$STD,$SKEW); |
# |
|
# 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, |
|
mean_tries => $mean, |
|
std_tries => $STD, |
|
skew_tries => $SKEW, |
|
num_solved => $Solved, |
|
num_override => $solved, |
|
per_wrong => $wrongpercent, |
|
deg_of_diff => $DegOfDiff }; |
} |
} |
|
|
sub execute_SQL_request { |
sub execute_SQL_request { |