[LON-CAPA-cvs] cvs: loncom /interface lonmeta.pm /interface/statistics lonproblemstatistics.pm /metadata_database/LONCAPA lonmetadata.pm
matthew
lon-capa-cvs@mail.lon-capa.org
Fri, 16 Apr 2004 21:43:56 -0000
This is a MIME encoded message
--matthew1082151836
Content-Type: text/plain
matthew Fri Apr 16 17:43:56 2004 EDT
Modified files:
/loncom/metadata_database/LONCAPA lonmetadata.pm
/loncom/interface lonmeta.pm
/loncom/interface/statistics lonproblemstatistics.pm
Log:
lonmeta.pm: Added degree of discrimination output.
Added 'detailed assessment statistical data' output, a table of classes,
sections, and various statistics which make up the 'overall assessment
statistical data'.
lonmetadata.pm: Documented data storage in nohist_resevaldata.db
&process_dynmaic_metadata now uses a weighted average for statistics, and
reports the sum of the maximum number of students per class as 'stdno',
since there may be multiple entries per class.
Added &dynamic_metadata_storage which prepares statistical data for
storage in nohist_resevaldata.db.
lonproblemstatistics.pm: Use lonmetadata::dynamic_metadata_storage to prepare
storage of dynamic metadata.
--matthew1082151836
Content-Type: text/plain
Content-Disposition: attachment; filename="matthew-20040416174356.txt"
Index: loncom/metadata_database/LONCAPA/lonmetadata.pm
diff -u loncom/metadata_database/LONCAPA/lonmetadata.pm:1.7 loncom/metadata_database/LONCAPA/lonmetadata.pm:1.8
--- loncom/metadata_database/LONCAPA/lonmetadata.pm:1.7 Wed Apr 14 16:35:29 2004
+++ loncom/metadata_database/LONCAPA/lonmetadata.pm Fri Apr 16 17:43:56 2004
@@ -1,6 +1,6 @@
# The LearningOnline Network with CAPA
#
-# $Id: lonmetadata.pm,v 1.7 2004/04/14 20:35:29 matthew Exp $
+# $Id: lonmetadata.pm,v 1.8 2004/04/16 21:43:56 matthew Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -410,6 +410,48 @@
=pod
+=item nohist_resevaldata.db data structure
+
+The nohist_resevaldata.db file has the following possible keys:
+
+ Statistics Data (values are integers, perl times, or real numbers)
+ ------------------------------------------
+ $course___$resource___avetries
+ $course___$resource___count
+ $course___$resource___difficulty
+ $course___$resource___stdno
+ $course___$resource___timestamp
+
+ Evaluation Data (values are on a 1 to 5 scale)
+ ------------------------------------------
+ $username@$dom___$resource___clear
+ $username@$dom___$resource___comments
+ $username@$dom___$resource___depth
+ $username@$dom___$resource___technical
+ $username@$dom___$resource___helpful
+
+ Course Context Data
+ ------------------------------------------
+ $course___$resource___course course id
+ $course___$resource___comefrom resource preceeding this resource
+ $course___$resource___goto resource following this resource
+ $course___$resource___usage resource containing this resource
+
+ New statistical data storage
+ ------------------------------------------
+ $course&$sec&$numstud___$resource___stats
+ $sec is a string describing the sections: all, 1 2, 1 2 3,...
+ Value is a '&' deliminated list of key=value pairs.
+ Possible keys are (currently) disc,course,sections,difficulty,
+ stdno, timestamp
+
+=cut
+
+######################################################################
+######################################################################
+
+=pod
+
=item &process_reseval_data
Process a nohist_resevaldata hash into a more complex data structure.
@@ -474,13 +516,15 @@
# $source is $cid\_$sec\_$stdno
# $value is stat1=value&stat2=value&stat3=value,....
#
- my ($cid,$sec,$stdno)=split('_',$source);
- my $crssec = $cid.'_'.$sec;
+ my ($cid,$sec,$stdno)=split('&',$source);
+ my $crssec = $cid.'&'.$sec;
my @Data = split('&',$value);
my %Statistics;
while (my ($key,$value) = split('=',pop(@Data))) {
$Statistics{$key} = $value;
}
+ $sec =~ s:("$|^")::g;
+ $Statistics{'sections'} = $sec;
#
# Only store the data if the number of students is greater
# than the data already stored
@@ -522,26 +566,71 @@
my %data;
my $resdata = $DynamicData->{$url};
#
- # Get the statistical data
- foreach my $type (qw/avetries difficulty stdno/) {
- my $count;
+ # Get the statistical data - Use a weighted average
+ foreach my $type (qw/avetries difficulty disc/) {
+ my $studentcount;
my $sum;
my @Values;
+ my @Students;
#
+ # Old data
foreach my $coursedata (values(%{$resdata->{'statistics'}}),
values(%{$resdata->{'stats'}})) {
if (ref($coursedata) eq 'HASH' && exists($coursedata->{$type})) {
- $count++;
- $sum += $coursedata->{$type};
+ $studentcount += $coursedata->{'stdno'};
+ $sum += ($coursedata->{$type}*$coursedata->{'stdno'});
push(@Values,$coursedata->{$type});
+ push(@Students,$coursedata->{'stdno'});
}
}
- if ($count) {
- $data{$type} = $sum/$count;
+ if (exists($resdata->{'stats'})) {
+ foreach my $identifier (sort(keys(%{$resdata->{'stats'}}))) {
+ my $coursedata = $resdata->{'stats'}->{$identifier};
+ $studentcount += $coursedata->{'stdno'};
+ $sum += $coursedata->{$type}*$coursedata->{'stdno'};
+ push(@Values,$coursedata->{$type});
+ push(@Students,$coursedata->{'stdno'});
+ }
+ }
+ #
+ # New data
+ if (defined($studentcount) && $studentcount>0) {
+ $data{$type} = $sum/$studentcount;
$data{$type.'_list'} = join(',',@Values);
}
}
#
+ # Find out the number of students who have completed the resource...
+ my $stdno;
+ foreach my $coursedata (values(%{$resdata->{'statistics'}}),
+ values(%{$resdata->{'stats'}})) {
+ if (ref($coursedata) eq 'HASH' && exists($coursedata->{'stdno'})) {
+ $stdno += $coursedata->{'stdno'};
+ }
+ }
+ if (exists($resdata->{'stats'})) {
+ #
+ # For the number of students, take the maximum found for the class
+ my $current_course;
+ my $coursemax=0;
+ foreach my $identifier (sort(keys(%{$resdata->{'stats'}}))) {
+ my $coursedata = $resdata->{'stats'}->{$identifier};
+ if (! defined($current_course)) {
+ $current_course = $coursedata->{'course'};
+ }
+ if ($current_course ne $coursedata->{'course'}) {
+ $stdno += $coursemax;
+ $coursemax = 0;
+ $current_course = $coursedata->{'course'};
+ }
+ if ($coursemax < $coursedata->{'stdno'}) {
+ $coursemax = $coursedata->{'stdno'};
+ }
+ }
+ $stdno += $coursemax; # pick up the final course in the list
+ }
+ $data{'stdno'}=$stdno;
+ #
# Get the context data
foreach my $type (qw/course goto comefrom/) {
if (defined($resdata->{$type}) &&
@@ -581,9 +670,33 @@
$comments .= '</div>';
$data{'comments'} = $comments;
#
+ if (exists($resdata->{'stats'})) {
+ $data{'stats'} = $resdata->{'stats'};
+ }
+ #
return %data;
}
+sub dynamic_metadata_storage {
+ my ($data) = @_;
+ my %Store;
+ my $courseid = $data->{'course'};
+ my $sections = $data->{'sections'};
+ my $numstu = $data->{'num_students'};
+ my $urlres = $data->{'urlres'};
+ my $key = $courseid.'&'.$sections.'&'.$numstu.'___'.$urlres.'___stats';
+ $Store{$key} =
+ 'course='.$courseid.'&'.
+ 'sections='.$sections.'&'.
+ 'timestamp='.time.'&'.
+ 'stdno='.$data->{'num_students'}.'&'.
+ 'avetries='.$data->{'mean_tries'}.'&'.
+ 'difficulty='.$data->{'deg_of_diff'};
+ if (exists($data->{'deg_of_disc'})) {
+ $Store{$key} .= '&'.'disc='.$data->{'deg_of_disc'};
+ }
+ return %Store;
+}
######################################################################
######################################################################
Index: loncom/interface/lonmeta.pm
diff -u loncom/interface/lonmeta.pm:1.72 loncom/interface/lonmeta.pm:1.73
--- loncom/interface/lonmeta.pm:1.72 Thu Apr 15 14:06:29 2004
+++ loncom/interface/lonmeta.pm Fri Apr 16 17:43:56 2004
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Metadata display handler
#
-# $Id: lonmeta.pm,v 1.72 2004/04/15 18:06:29 matthew Exp $
+# $Id: lonmeta.pm,v 1.73 2004/04/16 21:43:56 matthew Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -193,7 +193,8 @@
'technical' => 'Resource is technically correct',
'avetries' => 'Average number of tries till solved',
'stdno' => 'Total number of students who have worked on this problem',
- 'difficulty' => 'Degree of difficulty'
+ 'difficulty' => 'Degree of difficulty',
+ 'disc' => 'Degree of discrimination',
);
}
@@ -283,7 +284,7 @@
return &evalgraph($value);
}
# Difficulty
- if ($type eq 'difficulty') {
+ if ($type eq 'difficulty' || $type eq 'disc') {
return &diffgraph($value);
}
# List of courses
@@ -589,6 +590,8 @@
$r->rflush();
my %items=&fieldnames();
my %dynmeta=&dynamicmeta($uri);
+ &Apache::lonnet::logthis('dynamic metadata keys:'.$/.
+ join("\n",keys(%dynmeta)));
#
# General Access and Usage Statistics
if (exists($dynmeta{'count'}) ||
@@ -613,23 +616,88 @@
}
#
# Assessment statistics
- if ($uri=~/\.(problem|exam|quiz|assess|survey|form)$/ &&
- (exists($dynmeta{'stdno'}) ||
- exists($dynmeta{'avetries'}) ||
- exists($dynmeta{'difficulty'}))) {
- # This is an assessment, print assessment data
- $r->print('<h4>'.&mt('Assessment Statistical Data').'</h4>'.
- '<table cellspacing=2 border=0>');
- foreach ('stdno','avetries','difficulty') {
- $r->print('<tr><td bgcolor="#AAAAAA">'.$lt{$_}.'</td>'.
+ if ($uri=~/\.(problem|exam|quiz|assess|survey|form)$/) {
+ if (exists($dynmeta{'stdno'}) ||
+ exists($dynmeta{'avetries'}) ||
+ exists($dynmeta{'difficulty'}) ||
+ exists($dynmeta{'disc'})) {
+ # This is an assessment, print assessment data
+ $r->print('<h4>'.
+ &mt('Overall Assessment Statistical Data').
+ '</h4>'.
+ '<table cellspacing=2 border=0>');
+ $r->print('<tr><td bgcolor="#AAAAAA">'.$lt{'stdno'}.'</td>'.
'<td bgcolor="#CCCCCC">'.
- &prettyprint($_,sprintf('%5.2f',$dynmeta{$_})).'</td>'.
- "</tr>\n");
+ &prettyprint('stdno',$dynmeta{'stdno'}).
+ '</td>'."</tr>\n");
+ foreach ('avetries','difficulty','disc') {
+ $r->print('<tr><td bgcolor="#AAAAAA">'.$lt{$_}.'</td>'.
+ '<td bgcolor="#CCCCCC">'.
+ &prettyprint($_,sprintf('%5.2f',$dynmeta{$_})).
+ '</td>'."</tr>\n");
+ }
+ $r->print('</table>');
+ }
+ if (exists($dynmeta{'stats'})) {
+ #
+ # New assessment statistics
+ $r->print('<h4>'.
+ &mt('Detailed Assessment Statistical Data').
+ '</h4>');
+ my $table = '<table cellspacing=2 border=0>'.
+ '<tr>'.
+ '<th>Course</th>'.
+ '<th>Section(s)</th>'.
+ '<th>Num Students</th>'.
+ '<th>Mean Tries</th>'.
+ '<th>Degree of Difficulty</th>'.
+ '<th>Degree of Discrimination</th>'.
+ '<th>Time of computation</th>'.
+ '</tr>'.$/;
+ foreach my $identifier (sort(keys(%{$dynmeta{'stats'}}))) {
+ my $data = $dynmeta{'stats'}->{$identifier};
+ my $course = $data->{'course'};
+ my %courseinfo = &Apache::lonnet::coursedescription($course);
+ if (! exists($courseinfo{'num'}) || $courseinfo{'num'} eq '') {
+ &Apache::lonnet::logthis('lookup for '.$course.' failed');
+ next;
+ }
+ $table .= '<tr>';
+ $table .=
+ '<td><nobr>'.$courseinfo{'description'}.'</nobr></td>';
+ $table .=
+ '<td align="right">'.$data->{'sections'}.'</td>';
+ $table .=
+ '<td align="right">'.$data->{'stdno'}.'</td>';
+ foreach ('avetries','difficulty','disc') {
+ $table .= '<td align="right">';
+ if (exists($data->{$_})) {
+ $table .= sprintf('%.2f',$data->{$_}).' ';
+ } else {
+ $table .= '';
+ }
+ $table .= '</td>';
+ }
+ $table .=
+ '<td><nobr>'.
+ &Apache::lonlocal::locallocaltime($data->{'timestamp'}).
+ '</nobr></td>';
+ $table .=
+ '</tr>'.$/;
+ }
+ $table .= '</table>'.$/;
+ $r->print($table);
+ } else {
+ $r->print('No new dynamic data found.');
}
- $r->print('</table>');
} else {
- $r->print('<h4>'.&mt('No Assessment Statistical Data is available for this resource').'</h4>');
+ $r->print('<h4>'.
+ &mt('No Assessment Statistical Data is available for this resource').
+ '</h4>');
}
+
+ #
+ #
if (exists($dynmeta{'clear'}) ||
exists($dynmeta{'depth'}) ||
exists($dynmeta{'helpful'}) ||
Index: loncom/interface/statistics/lonproblemstatistics.pm
diff -u loncom/interface/statistics/lonproblemstatistics.pm:1.83 loncom/interface/statistics/lonproblemstatistics.pm:1.84
--- loncom/interface/statistics/lonproblemstatistics.pm:1.83 Tue Apr 6 11:45:13 2004
+++ loncom/interface/statistics/lonproblemstatistics.pm Fri Apr 16 17:43:56 2004
@@ -1,6 +1,6 @@
# The LearningOnline Network with CAPA
#
-# $Id: lonproblemstatistics.pm,v 1.83 2004/04/06 15:45:13 matthew Exp $
+# $Id: lonproblemstatistics.pm,v 1.84 2004/04/16 21:43:56 matthew Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -55,6 +55,7 @@
use Apache::lonhtmlcommon;
use Apache::loncoursedata;
use Apache::lonstatistics;
+use LONCAPA::lonmetadata();
use Apache::lonlocal;
use Spreadsheet::WriteExcel;
use Apache::lonstathelpers();
@@ -1453,22 +1454,17 @@
}
#
# Store in metadata if computations were done for all students
- if ($Apache::lonstatistics::SelectedSections[0] eq 'all' &&
- $data->{'num_students'} > 1) {
- my %storestats;
- #
+ if ($data->{'num_students'} > 1) {
+ my @Sections = @Apache::lonstatistics::SelectedSections;
+ my $sections = '"'.join(' ',@Sections).'"';
+ $sections =~ s/&+/_/g; # Ensure no special characters
+ $data->{'sections'}=$sections;
+ $data->{'course'} = $ENV{'request.course.id'};
my $urlres=(&Apache::lonnet::decode_symb($resource->{'symb'}))[2];
+ $data->{'urlres'}=$urlres;
+ my %storestats =
+ &LONCAPA::lonmetadata::dynamic_metadata_storage($data);
my ($dom,$user) = $urlres=~/^(\w+)\/(\w+)/;
- my $preamble = $courseid.'___'.$urlres.'___';
- #
- $storestats{$preamble.'timestamp'} = time;
- $storestats{$preamble.'stdno'} = $data->{'num_students'};
- $storestats{$preamble.'avetries'} = $data->{'mean_tries'};
- $storestats{$preamble.'difficulty'} = $data->{'deg_of_diff'};
- if ($SelectedFields{'deg_of_disc'}) {
- $storestats{$preamble.'discrimination'} = $data->{'deg_of_disc'};
- }
- #
&Apache::lonnet::put('nohist_resevaldata',\%storestats,$dom,$user);
}
return $data;
--matthew1082151836--