version 1.55, 2002/07/08 13:38:52
|
version 1.58, 2002/07/08 16:50:03
|
Line 245 sub FormatStudentData {
|
Line 245 sub FormatStudentData {
|
my $problem = $CacheData{$problemID.':problem'}; |
my $problem = $CacheData{$problemID.':problem'}; |
my $LatestVersion = $CacheData{$name.":version:$problem"}; |
my $LatestVersion = $CacheData{$name.":version:$problem"}; |
|
|
|
# Output blanks for all the parts of this problem if there |
|
# is no version information about the current problem. |
if(!$LatestVersion) { |
if(!$LatestVersion) { |
foreach my $part (split(/\:/,$CacheData{$sequence.':'. |
foreach my $part (split(/\:/,$CacheData{$sequence.':'. |
$problemID. |
$problemID. |
Line 257 sub FormatStudentData {
|
Line 259 sub FormatStudentData {
|
} |
} |
|
|
my %partData=undef; |
my %partData=undef; |
#initialize data, displays skips correctly |
# Initialize part data, display skips correctly |
|
# Skip refers to when a student made no submissions on that |
|
# part/problem. |
foreach my $part (split(/\:/,$CacheData{$sequence.':'. |
foreach my $part (split(/\:/,$CacheData{$sequence.':'. |
$problemID. |
$problemID. |
':parts'})) { |
':parts'})) { |
$partData{$part.':tries'}=0; |
$partData{$part.':tries'}=0; |
$partData{$part.':code'}=' '; |
$partData{$part.':code'}=' '; |
} |
} |
|
|
|
# Looping through all the versions of each part, starting with the |
|
# oldest version. Basically, it gets the most recent |
|
# set of grade data for each part. |
for(my $Version=1; $Version<=$LatestVersion; $Version++) { |
for(my $Version=1; $Version<=$LatestVersion; $Version++) { |
foreach my $part (split(/\:/,$CacheData{$sequence.':'. |
foreach my $part (split(/\:/,$CacheData{$sequence.':'. |
$problemID. |
$problemID. |
Line 271 sub FormatStudentData {
|
Line 279 sub FormatStudentData {
|
|
|
if(!defined($CacheData{$name.":$Version:$problem". |
if(!defined($CacheData{$name.":$Version:$problem". |
":resource.$part.solved"})) { |
":resource.$part.solved"})) { |
|
# No grade for this submission, so skip |
next; |
next; |
} |
} |
|
|
Line 294 sub FormatStudentData {
|
Line 303 sub FormatStudentData {
|
} |
} |
} |
} |
|
|
|
# All grades (except for versionless parts) are displayed as links |
|
# to their submission record. Loop through all the parts for the |
|
# current problem in the correct order and prepare the output links |
$Str.='<a href="/adm/grades?symb='. |
$Str.='<a href="/adm/grades?symb='. |
&Apache::lonnet::escape($problem). |
&Apache::lonnet::escape($problem). |
'&student='.$sname.'&domain='.$sdom.'&command=submission">'; |
'&student='.$sname.'&domain='.$sdom.'&command=submission">'; |
Line 319 sub FormatStudentData {
|
Line 331 sub FormatStudentData {
|
$Str.='</a>'; |
$Str.='</a>'; |
} |
} |
|
|
|
# Output the number of correct answers for the current sequence. |
|
# This part takes up 6 character slots, but is formated right |
|
# justified. |
my $spacesNeeded=$CacheData{$sequence.':columnWidth'}-$characterCount; |
my $spacesNeeded=$CacheData{$sequence.':columnWidth'}-$characterCount; |
$spacesNeeded -= 3; |
$spacesNeeded -= 3; |
$Str .= (' 'x$spacesNeeded); |
$Str .= (' 'x$spacesNeeded); |
Line 331 sub FormatStudentData {
|
Line 346 sub FormatStudentData {
|
$Str .= $spacePadding; |
$Str .= $spacePadding; |
} |
} |
|
|
|
# Output the total correct problems over the total number of problems. |
|
# I don't like this type of formatting, but it is a solution. Need |
|
# a way to dynamically determine the space requirements. |
my $outputProblemsSolved = sprintf( "%4d", $problemsSolved ); |
my $outputProblemsSolved = sprintf( "%4d", $problemsSolved ); |
my $outputTotalProblems = sprintf( "%4d", $totalProblems ); |
my $outputTotalProblems = sprintf( "%4d", $totalProblems ); |
$Str .= '<font color="#000088">'.$outputProblemsSolved. |
$Str .= '<font color="#000088">'.$outputProblemsSolved. |
Line 672 here in the future.
|
Line 690 here in the future.
|
|
|
=item &DownloadPrerequisiteData() |
=item &DownloadPrerequisiteData() |
|
|
Collects lastname, generation, middlename, firstname PID, and section for each |
Collects lastname, generation, middlename, firstname, PID, and section for each |
student from their environment database. The list of students is built from |
student from their environment database. The list of students is built from |
collecting a classlist for the course that is to be displayed. |
collecting a classlist for the course that is to be displayed. |
|
|
Line 793 tie hash to database later.
|
Line 811 tie hash to database later.
|
|
|
=pod |
=pod |
|
|
|
=item &ProcessTopResourceMap() |
|
|
|
Trace through the "big hash" created in rat/lonuserstate.pm::loadmap. |
|
Basically, this function organizes a subset of the data and stores it in |
|
cached data. The data stored is the problems, sequences, sequence titles, |
|
parts of problems, and their ordering. Column width information is also |
|
partially handled here on a per sequence basis. |
|
|
|
=over 4 |
|
|
|
Input: $ChartDB, $c |
|
|
|
$ChartDB: The name of the cache database file |
|
|
|
$c: The connection class used to determine if an abort has been sent to the |
|
browser |
|
|
|
Output: A string that contains an error message or "OK" if everything went |
|
smoothly. |
|
|
|
=back |
|
|
=cut |
=cut |
|
|
sub ProcessTopResourceMap { |
sub ProcessTopResourceMap { |
Line 821 sub ProcessTopResourceMap {
|
Line 861 sub ProcessTopResourceMap {
|
return 'Could not tie cache hash.'; |
return 'Could not tie cache hash.'; |
} |
} |
|
|
|
# Initialize state machine. Set information pointing to top level map. |
my (@sequences, @currentResource, @finishResource); |
my (@sequences, @currentResource, @finishResource); |
my ($currentSequence, $currentResourceID, $lastResourceID); |
my ($currentSequence, $currentResourceID, $lastResourceID); |
|
|
Line 889 sub ProcessTopResourceMap {
|
Line 930 sub ProcessTopResourceMap {
|
':'.$currentResourceID; |
':'.$currentResourceID; |
} |
} |
|
|
#Get Parts for problem |
# Get Parts for problem |
my $meta=$hash{'src_'.$currentResourceID}; |
my $meta=$hash{'src_'.$currentResourceID}; |
foreach (split(/\,/,&Apache::lonnet::metadata($meta,'keys'))) { |
foreach (split(/\,/,&Apache::lonnet::metadata($meta,'keys'))) { |
if($_=~/^stores\_(\d+)\_tries$/) { |
if($_=~/^stores\_(\d+)\_tries$/) { |
Line 906 sub ProcessTopResourceMap {
|
Line 947 sub ProcessTopResourceMap {
|
} |
} |
} |
} |
|
|
#if resource == finish resource |
# if resource == finish resource, then it is the end of a sequence/page |
if($currentResourceID eq $lastResourceID) { |
if($currentResourceID eq $lastResourceID) { |
#pop off last resource of sequence |
# pop off last resource of sequence |
$currentResourceID=pop(@currentResource); |
$currentResourceID=pop(@currentResource); |
$lastResourceID=pop(@finishResource); |
$lastResourceID=pop(@finishResource); |
|
|
Line 940 sub ProcessTopResourceMap {
|
Line 981 sub ProcessTopResourceMap {
|
(scalar @titleLength); |
(scalar @titleLength); |
} |
} |
} else { |
} else { |
|
# Remove sequence from list, if it contains no problems to |
|
# display. |
$CacheData{'orderedSequences'}=~s/$currentSequence//; |
$CacheData{'orderedSequences'}=~s/$currentSequence//; |
$CacheData{'orderedSequences'}=~s/::/:/g; |
$CacheData{'orderedSequences'}=~s/::/:/g; |
$CacheData{'orderedSequences'}=~s/^:|:$//g; |
$CacheData{'orderedSequences'}=~s/^:|:$//g; |
Line 952 sub ProcessTopResourceMap {
|
Line 995 sub ProcessTopResourceMap {
|
} |
} |
|
|
# MOVE!!! |
# MOVE!!! |
#move to next resource |
# move to next resource |
unless(defined($hash{'to_'.$currentResourceID})) { |
unless(defined($hash{'to_'.$currentResourceID})) { |
# big problem, need to handle. Next is probably wrong |
# big problem, need to handle. Next is probably wrong |
last; |
last; |
Line 981 sub ProcessTopResourceMap {
|
Line 1024 sub ProcessTopResourceMap {
|
return 'OK'; |
return 'OK'; |
} |
} |
|
|
|
=pod |
|
|
|
=item &ProcessSection() |
|
|
|
Determine the section number for a student for the class. A student can have |
|
multiple sections for the same class. The correct one is chosen. |
|
|
|
=over 4 |
|
|
|
Input: $sectionData, $courseid, $ActiveFlag |
|
|
|
$sectionData: A pointer to a hash containing all section data for this |
|
student for the class |
|
|
|
$courseid: The course ID. |
|
|
|
$ActiveFlag: The student's active status (Active/Expired) |
|
|
|
Output: $oldsection, $cursection, or -1 |
|
|
|
$oldsection and $cursection and sections number that will be displayed in the |
|
chart. |
|
|
|
-1 is returned if an error occurs. |
|
|
|
=back |
|
|
|
=cut |
|
|
sub ProcessSection { |
sub ProcessSection { |
my ($sectionData, $courseid,$ActiveFlag)=@_; |
my ($sectionData, $courseid,$ActiveFlag)=@_; |
$courseid=~s/\_/\//g; |
$courseid=~s/\_/\//g; |
Line 1035 sub ProcessSection {
|
Line 1107 sub ProcessSection {
|
return '-1'; |
return '-1'; |
} |
} |
|
|
|
=pod |
|
|
|
=item &ProcessStudentInformation() |
|
|
|
Takes data downloaded for a student and breaks it up into managable pieces and |
|
stored in cache data. The username, domain, class related date, PID, |
|
full name, and section are all processed here. |
|
|
|
=over 4 |
|
|
|
Input: $CacheData, $studentInformation, $section, $date, $name, $courseID |
|
|
|
$CacheData: A hash pointer to the cached data |
|
|
|
$studentInformation: Student information is what was requested in |
|
&DownloadPrerequistedData(). See that function for what data is requested. |
|
|
|
$section: A hash pointer to class section related information. |
|
|
|
$date: A composite of the start and end date for this class for this |
|
student. Format: end:start |
|
|
|
$name: the username:domain information |
|
|
|
$courseID: The course ID |
|
|
|
Output: None |
|
|
|
*NOTE: There is no return value, but if an error occurs a key is added to |
|
the cache data with the value being the error message. The key is |
|
username:domain:error. It will only exist if an error occurs. |
|
|
|
=back |
|
|
|
=cut |
|
|
sub ProcessStudentInformation { |
sub ProcessStudentInformation { |
my ($CacheData,$studentInformation,$section,$date,$name,$courseID,$c)=@_; |
my ($CacheData,$studentInformation,$section,$date,$name,$courseID)=@_; |
my ($studentName,$studentDomain) = split(/\:/,$name); |
my ($studentName,$studentDomain) = split(/\:/,$name); |
|
|
$CacheData->{$name.':username'}=$studentName; |
$CacheData->{$name.':username'}=$studentName; |
Line 1066 sub ProcessStudentInformation {
|
Line 1174 sub ProcessStudentInformation {
|
$CacheData->{$name.':section'}=''; |
$CacheData->{$name.':section'}=''; |
} |
} |
|
|
return 0; |
return; |
} |
} |
|
|
|
=pod |
|
|
|
=item &ProcessClassList() |
|
|
|
Taking the class list dumped from &DownloadPrerequisiteData(), all the |
|
students and their non-class information is processed using the |
|
&ProcessStudentInformation() function. A date stamp is also recorded for |
|
when the data was processed. |
|
|
|
=over 4 |
|
|
|
Input: $classlist, $courseID, $ChartDB, $c |
|
|
|
$classlist: The hash of data collected about a student from |
|
&DownloadPrerequisteData(). The hash contains a list of students, a pointer |
|
to a hash of student information for each student, and each student's section |
|
number. |
|
|
|
$courseID: The course ID |
|
|
|
$ChartDB: The name of the cache database file. |
|
|
|
$c: The connection class used to determine if an abort has been sent to the |
|
browser |
|
|
|
Output: @names |
|
|
|
@names: An array of students whose information has been processed, and are to |
|
be considered in an arbitrary order. |
|
|
|
=back |
|
|
|
=cut |
|
|
sub ProcessClassList { |
sub ProcessClassList { |
my ($classlist,$courseID,$ChartDB,$c)=@_; |
my ($classlist,$courseID,$ChartDB,$c)=@_; |
my @names=(); |
my @names=(); |
Line 1089 sub ProcessClassList {
|
Line 1231 sub ProcessClassList {
|
$classlist->{$name.':studentInformation'}, |
$classlist->{$name.':studentInformation'}, |
$classlist->{$name.':section'}, |
$classlist->{$name.':section'}, |
$classlist->{$name}, |
$classlist->{$name}, |
$name,$courseID,$c); |
$name,$courseID); |
} |
} |
|
|
# Time of download |
# Time of download |
Line 1100 sub ProcessClassList {
|
Line 1242 sub ProcessClassList {
|
return @names; |
return @names; |
} |
} |
|
|
|
=pod |
|
|
|
=item &ProcessStudentData() |
|
|
|
Takes the course data downloaded for a student in |
|
&DownloadStudentCourseInformation() and breaks it up into key value pairs |
|
to be stored in the cached data. The keys are comprised of the |
|
$username:$domain:$keyFromCourseDatabase. The student username:domain is |
|
stored away signifying that the student's information has been downloaded and |
|
can be reused from cached data. |
|
|
|
=over 4 |
|
|
|
Input: $courseData, $name, $ChartDB |
|
|
|
$courseData: A hash pointer that points to the course data downloaded for a |
|
student. |
|
|
|
$name: username:domain |
|
|
|
$ChartDB: The name of the cache database file which will allow the data to |
|
be written to the cache. |
|
|
|
Output: None |
|
|
|
*NOTE: There is no output, but an error message is stored away in the cache |
|
data. This is checked in &FormatStudentData(). The key username:domain:error |
|
will only exist if an error occured. The error is an error from |
|
&DownloadStudentCourseInformation(). |
|
|
|
=back |
|
|
|
=cut |
|
|
sub ProcessStudentData { |
sub ProcessStudentData { |
my ($courseData, $name, $ChartDB)=@_; |
my ($courseData, $name, $ChartDB)=@_; |
|
|
Line 1147 Output: None
|
Line 1323 Output: None
|
|
|
=cut |
=cut |
|
|
|
# For all data, if ENV data doesn't exist for it, default values is used. |
sub ProcessFormData { |
sub ProcessFormData { |
my ($ChartDB, $isCached)=@_; |
my ($ChartDB, $isCached)=@_; |
my %CacheData; |
my %CacheData; |
|
|
if(tie(%CacheData,'GDBM_File',$ChartDB,&GDBM_WRCREAT,0640)) { |
if(tie(%CacheData,'GDBM_File',$ChartDB,&GDBM_WRCREAT,0640)) { |
|
# Ignore $ENV{'form.refresh'} |
|
# Ignore $ENV{'form.recalculate'} |
|
|
if(defined($ENV{'form.sort'})) { |
if(defined($ENV{'form.sort'})) { |
$CacheData{'form.sort'}=$ENV{'form.sort'}; |
$CacheData{'form.sort'}=$ENV{'form.sort'}; |
} elsif(!defined($CacheData{'form.sort'})) { |
} elsif(!defined($CacheData{'form.sort'})) { |
$CacheData{'form.sort'}='username'; |
$CacheData{'form.sort'}='username'; |
} |
} |
|
|
# Ignore $ENV{'form.refresh'} |
|
# Ignore $ENV{'form.recalculate'} |
|
|
|
if(defined($ENV{'form.status'})) { |
if(defined($ENV{'form.status'})) { |
$CacheData{'form.status'}=$ENV{'form.status'}; |
$CacheData{'form.status'}=$ENV{'form.status'}; |
} elsif(!defined($CacheData{'form.status'})) { |
} elsif(!defined($CacheData{'form.status'})) { |
$CacheData{'form.status'}='Active'; |
$CacheData{'form.status'}='Active'; |
} |
} |
|
|
|
# $found checks for any instances of form data in the ENV. If it is |
|
# missing I assume the chrt button on the remote has been pressed. |
my @headings=(); |
my @headings=(); |
my @sequences=(); |
my @sequences=(); |
my $found=0; |
my $found=0; |
Line 1200 sub ProcessFormData {
|
Line 1379 sub ProcessFormData {
|
} |
} |
} |
} |
|
|
|
# !$found and !$isCached are how I determine if the chrt button |
|
# on the remote was pressed and needs to reset all the selections |
if(defined($ENV{'form.reset'}) || (!$found && !$isCached)) { |
if(defined($ENV{'form.reset'}) || (!$found && !$isCached)) { |
$CacheData{'form.reset'}='true'; |
$CacheData{'form.reset'}='true'; |
$CacheData{'form.status'}='Active'; |
$CacheData{'form.status'}='Active'; |
Line 1287 jobs.
|
Line 1468 jobs.
|
=item &ProcessFullName() |
=item &ProcessFullName() |
|
|
Takes lastname, generation, firstname, and middlename (or some partial |
Takes lastname, generation, firstname, and middlename (or some partial |
set of this data) and returns the full name version as a string. |
set of this data) and returns the full name version as a string. Format |
|
is Lastname generation, firstname middlename or a subset of this. |
|
|
=cut |
=cut |
|
|
Line 1519 functions return strings to BuildChart t
|
Line 1701 functions return strings to BuildChart t
|
|
|
=item &BuildChart() |
=item &BuildChart() |
|
|
The following is the process that BuildChart goes through to create the |
The following is the process that BuildChart goes through to |
html document. |
create the html document. |
|
|
-Start the lonchart document |
-Start the lonchart document |
-Test for access to the CacheData |
-Test for access to the CacheData |
-Download class list information if not using cached data |
-Download class list information if not using cached data |
-Sort students and print out table desciptive data |
-Sort students and print out table desciptive data |
-Output student data |
-Output student data |
-If recalculating, store a list of students, but only if all their data was |
-If recalculating, store a list of students, but only if all |
downloaded. Leave off the others. |
their data was downloaded. Leave off the others. |
-End document |
-End document |
|
|
=over 4 |
=over 4 |
Line 1715 sub handler {
|
Line 1897 sub handler {
|
$r->send_http_header; |
$r->send_http_header; |
return OK; |
return OK; |
} |
} |
|
|
unless($ENV{'request.course.fn'}) { |
unless($ENV{'request.course.fn'}) { |
my $requrl=$r->uri; |
my $requrl=$r->uri; |
$ENV{'user.error.msg'}="$requrl:bre:0:0:Course not initialized"; |
$ENV{'user.error.msg'}="$requrl:bre:0:0:Course not initialized"; |