--- loncom/interface/statistics/lonstudentassessment.pm 2003/06/10 19:19:57 1.55
+++ loncom/interface/statistics/lonstudentassessment.pm 2003/12/11 15:48:56 1.79
@@ -1,6 +1,6 @@
# The LearningOnline Network with CAPA
#
-# $Id: lonstudentassessment.pm,v 1.55 2003/06/10 19:19:57 matthew Exp $
+# $Id: lonstudentassessment.pm,v 1.79 2003/12/11 15:48:56 matthew Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -52,9 +52,12 @@ package Apache::lonstudentassessment;
use strict;
use Apache::lonstatistics;
use Apache::lonhtmlcommon;
+use Apache::loncommon();
use Apache::loncoursedata;
use Apache::lonnet; # for logging porpoises
+use Apache::lonlocal;
use Spreadsheet::WriteExcel;
+use Spreadsheet::WriteExcel::Utility();
#######################################################
#######################################################
@@ -138,8 +141,32 @@ Inputs:
#######################################################
sub BuildStudentAssessmentPage {
my ($r,$c)=@_;
+ #
undef($Statistics);
+ undef($show_links);
+ undef($output_mode);
+ undef($data);
+ undef($base);
+ undef($datadescription);
+ undef($single_student_mode);
+ #
+ my %Saveable_Parameters = ('Status' => 'scalar',
+ 'chartoutputmode' => 'scalar',
+ 'chartoutputdata' => 'scalar',
+ 'Section' => 'array',
+ 'StudentData' => 'array',
+ 'Maps' => 'array');
+ &Apache::loncommon::store_course_settings('chart',\%Saveable_Parameters);
+ &Apache::loncommon::restore_course_settings('chart',\%Saveable_Parameters);
+ #
+ &Apache::lonstatistics::PrepareClasslist();
+ #
+ $single_student_mode = 0;
$single_student_mode = 1 if ($ENV{'form.SelectedStudent'});
+ if ($ENV{'form.selectstudent'}) {
+ &Apache::lonstatistics::DisplayClasslist($r);
+ return;
+ }
#
# Print out the HTML headers for the interface
# This also parses the output mode selector
@@ -149,6 +176,7 @@ sub BuildStudentAssessmentPage {
$r->print(' ');
$r->rflush();
+ #
if (! exists($ENV{'form.notfirstrun'}) && ! $single_student_mode) {
return;
}
@@ -179,6 +207,16 @@ sub BuildStudentAssessmentPage {
@Students = @Apache::lonstatistics::Students;
}
#
+ # Perform generic initialization tasks
+ # Since we use lonnet::EXT to retrieve problem weights,
+ # to ensure current data we must clear the caches out.
+ # This makes sure that parameter changes at the student level
+ # are immediately reflected in the chart.
+ &Apache::lonnet::clear_EXT_cache_status();
+ #
+ # Clean out loncoursedata's package data, just to be safe.
+ &Apache::loncoursedata::clear_internal_caches();
+ #
# Call the initialize routine selected above
$initialize->($r);
foreach my $student (@Students) {
@@ -281,12 +319,16 @@ sub CreateInterface {
# $Str .= &CreateLegend();
$Str .= '
'."\n";
$Str .= '';
- $Str .= 'Sections ';
- $Str .= 'Student Data ';
- $Str .= 'Enrollment Status ';
- $Str .= 'Sequences and Folders ';
- $Str .= 'Output Format ';
- $Str .= 'Output Data ';
+ $Str .= ''.&mt('Sections').' ';
+ $Str .= ''.&mt('Student Data ').' ';
+ $Str .= ''.&mt('Enrollment Status').' ';
+ $Str .= ''.&mt('Sequences and Folders').' ';
+ $Str .= ''.&mt('Output Format').' '.
+ &Apache::loncommon::help_open_topic("Chart_Output_Formats").
+ ' ';
+ $Str .= ''.&mt('Output Data').' '.
+ &Apache::loncommon::help_open_topic("Chart_Output_Data").
+ ' ';
$Str .= ' '."\n";
#
$Str .= ''."\n";
@@ -313,8 +355,16 @@ sub CreateInterface {
$Str .= &CreateAndParseOutputDataSelector();
$Str .= ' '."\n";
$Str .= '
'."\n";
- $Str .= ' ';
- $Str .= ' 'x8;
+ $Str .= ' ';
+ $Str .= ' 'x5;
+ $Str .= ' ';
+ $Str .= ' 'x5;
+ $Str .= ' ';
+ $Str .= ' 'x5;
+ $Str .= ' ';
return $Str;
}
@@ -359,29 +409,12 @@ my @OutputOptions =
mode => 'excel',
show_links => 'no',
},
-# { name => 'multi-sheet Excel',
-# value => 'multi-sheet excel',
-# description => 'Output an Excel file (compatable with Excel 95), '.
-# 'with a seperate worksheet for each sequence you have selected '.
-# 'the data for each problem part '.
-# '(number of tries, status, points awarded) will be listed.',
-# mode => 'multi-sheet excel',
-# show_links => 'no',
-# },
-# { name => 'multi-sheet Excel, by section',
-# value => 'multi-sheet excel, by section',
-# description => 'Output an Excel file (compatable with Excel 95), '.
-# 'with a seperate worksheet for each sequence you have selected '.
-# 'the data for each problem part '.
-# '(number of tries, status, points awarded) will be listed. '.
-# 'There will be one Excel workbook for each section selected.',
-# mode => 'multi-sheet excel',
-# show_links => 'no',
-# },
{ name => 'CSV',
value => 'csv',
description => 'Output a comma seperated values file suitable for '.
- 'import into a spreadsheet.',
+ 'import into a spreadsheet program. Using this method as opposed '.
+ 'to Excel output allows you to organize your data before importing'.
+ ' it into a spreadsheet program.',
mode => 'csv',
show_links => 'no',
},
@@ -389,7 +422,7 @@ my @OutputOptions =
sub OutputDescriptions {
my $Str = '';
- $Str .= "Output Modes \n";
+ $Str .= "Output Formats \n";
$Str .= "\n";
foreach my $outputmode (@OutputOptions) {
$Str .=" ".$outputmode->{'name'}." \n";
@@ -402,6 +435,8 @@ sub OutputDescriptions {
sub CreateAndParseOutputSelector {
my $Str = '';
my $elementname = 'chartoutputmode';
+ &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
+ [$elementname]);
#
# Format for output options is 'mode, restrictions';
my $selected = 'html, without links';
@@ -428,7 +463,7 @@ sub CreateAndParseOutputSelector {
foreach my $option (@OutputOptions) {
$Str .= "\n".' {'value'} eq $selected);
- $Str .= ">".$option->{'name'}."<\/option>";
+ $Str .= ">".&mt($option->{'name'})."<\/option>";
}
$Str .= "\n";
return $Str;
@@ -438,61 +473,76 @@ sub CreateAndParseOutputSelector {
## Data selector stuff
##
my @OutputDataOptions =
- ( { name =>'Tries',
- base =>'tries',
- value => 'tries',
- shortdesc => 'Number of Tries before success on each Problem Part',
- longdesc =>'The number of tries before success on each problem part.',
- },
- { name =>'Parts Correct',
- base =>'tries',
- value => 'parts correct',
- shortdesc => 'Number of Problem Parts completed successfully.',
- longdesc => 'The Number of Problem Parts completed successfully.',
- },
- { name =>'Parts Correct & Maximums',
- base =>'tries',
- value => 'parts correct total',
- shortdesc => 'Number of Problem Parts completed successfully.',
- longdesc => 'The Number of Problem Parts completed successfully and '.
- 'the maximum possible for each student',
- },
- { name => 'Scores',
- base => 'scores',
- value => 'scores',
- shortdesc => 'Score on each Problem Part',
- longdesc =>'The students score on each problem part, computed as'.
- 'the part weight * part awarded',
- },
- { name => 'Scores Sum',
- base => 'scores',
- value => 'sum only',
- shortdesc => 'Sum of Scores on each Problem Part',
- longdesc =>'The total of the scores of the student on each problem'.
- ' part in the sequences or folders selected.',
- },
- { name => 'Scores Sum & Maximums',
- base => 'scores',
- value => 'sum and total',
- shortdesc => 'Total Score and Maximum Possible for each '.
- 'Sequence or Folder',
- longdesc => 'The total of the scores of the student on each problem'.
- ' and the maximum possible for that student on each Sequence or '.
- ' Folder.',
- },
- { name => 'Summary Table (Scores)',
- base => 'scores',
- value => 'final table scores',
- shortdesc => 'Summary of Scores',
- longdesc => '',
- },
- { name => 'Summary Table (Parts)',
- base => 'tries',
- value => 'final table parts',
- shortdesc => 'Summary of Parts Correct',
- longdesc => '',
- }
- );
+ (
+ { name => 'Scores Summary',
+ base => 'scores',
+ value => 'sum and total',
+ shortdesc => 'Total Score and Maximum Possible for each '.
+ 'Sequence or Folder',
+ longdesc => 'The score of each student as well as the '.
+ ' maximum possible on each Sequence or Folder.',
+ },
+ { name => 'Scores Per Problem',
+ base => 'scores',
+ value => 'scores',
+ shortdesc => 'Score on each Problem Part',
+ longdesc =>'The students score on each problem part, computed as'.
+ 'the part weight * part awarded',
+ },
+# { name => 'Scores Sum',
+# base => 'scores',
+# value => 'sum only',
+# shortdesc => 'Sum of Scores on each Problem Part',
+# longdesc =>'The total of the scores of the student on each problem'.
+# ' part in the sequences or folders selected.',
+# },
+# { name => 'Scores Summary Table Only',
+# base => 'scores',
+# value => 'final table scores',
+# shortdesc => 'Summary of Scores',
+# longdesc => 'The average score on each sequence or folder for the '.
+# 'selected students.',
+# },
+ { name =>'Tries',
+ base =>'tries',
+ value => 'tries',
+ shortdesc => 'Number of Tries before success on each Problem Part',
+ longdesc =>'The number of tries before success on each problem part.',
+ },
+ { name =>'Parts Correct',
+ base =>'tries',
+ value => 'parts correct total',
+ shortdesc => 'Number of Problem Parts completed successfully.',
+ longdesc => 'The Number of Problem Parts completed successfully and '.
+ 'the maximum possible for each student',
+ },
+# { name =>'Parts Correct',
+# base =>'tries',
+# value => 'parts correct',
+# shortdesc => 'Number of Problem Parts completed successfully.',
+# longdesc => 'The Number of Problem Parts completed successfully'.
+# ' on each sequence or folder.',
+# },
+# { name => 'Parts Summary Table Only',
+# base => 'tries',
+# value => 'final table parts',
+# shortdesc => 'Summary of Parts Correct',
+# longdesc => 'A summary table of the average number of problem parts '.
+# 'students were able to get correct on each sequence.',
+# },
+ );
+
+sub HTMLifyOutputDataDescriptions {
+ my $Str = '';
+ $Str .= "Output Data \n";
+ $Str .= "\n";
+ foreach my $option (@OutputDataOptions) {
+ $Str .= ' '.$option->{'name'}.' ';
+ $Str .= ''.$option->{'longdesc'}.' '."\n";
+ }
+ $Str .= " \n";
+ return $Str;
+}
sub CreateAndParseOutputDataSelector {
my $Str = '';
@@ -521,7 +571,7 @@ sub CreateAndParseOutputDataSelector {
foreach my $option (@OutputDataOptions) {
$Str .= "\n".' {'value'} eq $data);
- $Str .= ">".$option->{'name'}."<\/option>";
+ $Str .= ">".&mt($option->{'name'})."<\/option>";
}
$Str .= "\n";
return $Str;
@@ -562,6 +612,7 @@ sub html_initialize {
$padding = ' 'x3;
$count = 0;
$nodata_count = 0;
+ undef(%prog_state);
#
$r->print("".$ENV{'course.'.$ENV{'request.course.id'}.'.description'}.
" ".localtime(time)." ");
@@ -786,78 +837,6 @@ sub SingleStudentTotal {
=pod
-=head2 Multi-Sheet EXCEL subroutines
-
-=item &multi_sheet_excel_initialize($r)
-
-=item &multi_sheet_excel_outputstudent($r,$student)
-
-=item &multi_sheet_excel_finish($r)
-
-=cut
-
-#######################################################
-#######################################################
-{
-
-sub multi_sheet_excel_initialize {
- my ($r)=@_;
- $r->print("Not yet implemented ");
- #
- # Estimate the size of the file. We would like to have < 5 megs of data.
- my $max_size = 5000000;
- my $num_students = scalar(@Apache::lonstatistics::Students);
- my $num_sequences = 0;
- my $num_data_per_part = 2; # 'status' and 'numtries'
- my $fields_per_student = scalar(&get_student_fields_to_show());
- my $bytes_per_field = 20; # Back of the envelope calculation
- foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
- $num_sequences++ if ($seq->{'num_assess'} > 0);
- $fields_per_student += $num_data_per_part * $seq->{'num_assess_parts'};
- }
- my $size_estimate = $fields_per_student*$num_students*$bytes_per_field;
- #
- # Compute number of workbooks
- my $num_workbooks = 1;
- if ($size_estimate > $max_size) { # try to stay under 5 megs
- $num_workbooks += int($size_estimate / $max_size);
- }
-# if ($data eq ) {
-# if (@Apache::lonstatistics::SelectedSections > 1 &&
-# $Apache::lonstatistics::SelectedSections[0] ne 'all') {
-# $num_workbooks = scalar(@Apache::lonstatistics::SelectedSections);
-# } else {
-# # @Apache::lonstatistics::Sections contains 'all' as well.
-# $num_workbooks = scalar(@Apache::lonstatistics::Sections) - 1;
-# }
-# }
-
- $r->print("Maximum allowed size: ".$max_size." bytes ");
- $r->print("Number of students: ".$num_students." ");
- $r->print("Number of fields per student: ".$fields_per_student." ");
- $r->print("Total number of fields: ".($fields_per_student*$num_students).
- " ");
- $r->print("Bytes per field: ".$bytes_per_field." (estimated)"." ");
- $r->print("Estimated size: ".$size_estimate." bytes ");
- $r->print("Number of workbooks: ".$num_workbooks." ");
- $r->rflush();
- return;
-}
-
-sub multi_sheet_excel_outputstudent {
- my ($r,$student) = @_;
-}
-
-sub multi_sheet_excel_finish {
- my ($r) = @_;
-}
-
-}
-#######################################################
-#######################################################
-
-=pod
-
=head2 EXCEL subroutines
=item &excel_initialize($r)
@@ -882,10 +861,20 @@ my $cols_output;
my %prog_state; # progress window state
my $request_aborted;
+my $total_formula;
+
sub excel_initialize {
my ($r) = @_;
#
- $request_aborted = undef;
+ undef ($excel_sheet);
+ undef ($excel_workbook);
+ undef ($filename);
+ undef ($rows_output);
+ undef ($cols_output);
+ undef (%prog_state);
+ undef ($request_aborted);
+ undef ($total_formula);
+ #
my $total_columns = scalar(&get_student_fields_to_show());
foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
# Add 2 because we need a 'sum' and 'total' column for each
@@ -966,9 +955,7 @@ END
#
# Add a worksheet
my $sheetname = $ENV{'course.'.$ENV{'request.course.id'}.'.description'};
- if (length($sheetname) > 31) {
- $sheetname = substr($sheetname,0,31);
- }
+ $sheetname = &Apache::loncommon::clean_excel_name($sheetname);
$excel_sheet = $excel_workbook->addworksheet($sheetname);
#
# Put the course description in the header
@@ -1018,10 +1005,17 @@ END
}
#
# Add the remaining column headers
+ my $total_formula_string = '=0';
foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
$excel_sheet->write($rows_output+$row_offset,
$cols_output,$seq->{'title'});
if ($data eq 'tries' || $data eq 'scores') {
+ # Determine starting cell
+ $seq->{'Excel:startcell'}=
+ &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
+ ($rows_output,$cols_output);
+ $seq->{'Excel:startcol'}=$cols_output;
+ # Put the names of the problems and parts into the sheet
foreach my $res (@{$seq->{'contents'}}) {
next if ($res->{'type'} ne 'assessment');
if (scalar(@{$res->{'parts'}}) > 1) {
@@ -1036,16 +1030,34 @@ END
$res->{'title'});
}
}
- $excel_sheet->write($rows_output,$cols_output++,'score');
- $excel_sheet->write($rows_output,$cols_output++,'maximum');
- } elsif ($data eq 'sum and total' || $data eq 'parts correct total') {
- $excel_sheet->write($rows_output+1,$cols_output,'score');
- $excel_sheet->write($rows_output+1,$cols_output+1,'maximum');
- $cols_output += 2;
+ # Determine ending cell
+ $seq->{'Excel:endcell'} =
+ &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
+ ($rows_output,$cols_output-1);
+ $seq->{'Excel:endcol'}=$cols_output-1;
+ # Create the formula for summing up this sequence
+ $seq->{'Excel:sum'}= $excel_sheet->store_formula
+ ('=SUM('.$seq->{'Excel:startcell'}.
+ ':'.$seq->{'Excel:endcell'}.')');
+ }
+ # Determine cell the score is held in
+ $seq->{'Excel:scorecell'} =
+ &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
+ ($rows_output,$cols_output);
+ $seq->{'Excel:scorecol'}=$cols_output;
+ if ($data eq 'parts correct total') {
+ $excel_sheet->write($rows_output,$cols_output++,'parts correct');
} else {
- $cols_output++;
+ $excel_sheet->write($rows_output,$cols_output++,'score');
}
+ #
+ $total_formula_string.='+'.
+ &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
+ ($rows_output,$cols_output-1);
+ $excel_sheet->write($rows_output,$cols_output++,'maximum');
}
+ $excel_sheet->write($rows_output,$cols_output++,'Grand Total');
+ $total_formula = $excel_sheet->store_formula($total_formula_string);
#
# Bookkeeping
if ($data eq 'sum and total' || $data eq 'parts correct total') {
@@ -1066,7 +1078,12 @@ END
}
#
# Add the maximums for each sequence or assessment
+ my %total_cell_translation;
+ my $grand_total = 0;
foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
+ $total_cell_translation{$seq->{'Excel:scorecell'}} =
+ &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
+ ($rows_output,$seq->{'Excel:scorecol'});
my $weight;
my $max = 0;
foreach my $resource (@{$seq->{'contents'}}) {
@@ -1092,7 +1109,30 @@ END
if (! ($data eq 'sum only' || $data eq 'parts correct')) {
$excel_sheet->write($rows_output,$cols_output++,'');
}
- $excel_sheet->write($rows_output,$cols_output++,$max);
+ #
+ if ($data eq 'tries' || $data eq 'scores') {
+ my %replaceCells;
+ $replaceCells{$seq->{'Excel:startcell'}} =
+ &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
+ ($rows_output,$seq->{'Excel:startcol'});
+ $replaceCells{$seq->{'Excel:endcell'}} =
+ &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
+ ($rows_output,$seq->{'Excel:endcol'});
+ $excel_sheet->repeat_formula($rows_output,$cols_output++,
+ $seq->{'Excel:sum'},undef,
+ %replaceCells);
+ } else {
+ $excel_sheet->write($rows_output,$cols_output++,
+ $max);
+ }
+ $grand_total+=$max;
+ }
+ if ($data eq 'tries' || $data eq 'scores') {
+ $excel_sheet->repeat_formula($rows_output,$cols_output++,
+ $total_formula,undef,
+ %total_cell_translation);
+ } else {
+ $excel_sheet->write($rows_output,$cols_output++,$grand_total);
}
$rows_output++;
#
@@ -1109,6 +1149,8 @@ END
($r,'Excel File Compilation Status',
'Excel File Compilation Progress', $studentcount);
#
+ &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,
+ 'Processing first student');
return;
}
@@ -1135,7 +1177,13 @@ sub excel_outputstudent {
}
#
# Write out sequence scores and totals data
+ my %total_cell_translation;
foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
+ # Keep track of cells to translate in total cell
+ $total_cell_translation{$seq->{'Excel:scorecell'}} =
+ &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
+ ($rows_output,$seq->{'Excel:scorecol'});
+ #
my ($performance,$performance_length,$score,$seq_max,$rawdata);
if ($base eq 'tries') {
($performance,$performance_length,$score,$seq_max,$rawdata) =
@@ -1150,7 +1198,19 @@ sub excel_outputstudent {
foreach my $value (@$rawdata) {
$excel_sheet->write($rows_output,$cols_output++,$value);
}
- $excel_sheet->write($rows_output,$cols_output++,$score);
+ # Write a formula for the sum of this sequence
+ my %replaceCells;
+ $replaceCells{$seq->{'Excel:startcell'}} =
+ &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
+ ($rows_output,$seq->{'Excel:startcol'});
+ $replaceCells{$seq->{'Excel:endcell'}} =
+ &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
+ ($rows_output,$seq->{'Excel:endcol'});
+ # The undef is for the format
+ $excel_sheet->repeat_formula($rows_output,$cols_output++,
+ $seq->{'Excel:sum'},undef,
+ %replaceCells);
+ #
$excel_sheet->write($rows_output,$cols_output++,$seq_max);
} elsif ($data eq 'sum and total' || $data eq 'sum only' ||
$data eq 'parts correct' || $data eq 'parts correct total') {
@@ -1161,6 +1221,11 @@ sub excel_outputstudent {
}
}
#
+ $excel_sheet->repeat_formula($rows_output,$cols_output++,
+ $total_formula,undef,
+ %total_cell_translation);
+
+ #
# Bookkeeping
$rows_output++;
$cols_output=0;
@@ -1220,8 +1285,9 @@ sub csv_initialize{
my ($r) = @_;
#
# Clean up
- $filename = undef;
- $outputfile = undef;
+ undef($outputfile);
+ undef($filename);
+ undef($request_aborted);
undef(%prog_state);
#
# Deal with unimplemented requests
@@ -1425,43 +1491,56 @@ sub StudentTriesOnSequence {
$performance_length++;
my $symbol = ' '; # default to space
#
+ my $awarded = 0;
+ if (exists($resource_data->{'resource.'.$partnum.'.awarded'})) {
+ $awarded = $resource_data->{'resource.'.$partnum.'.awarded'};
+ $awarded = 0 if (! $awarded);
+ }
+ #
+ my $status = '';
if (exists($resource_data->{'resource.'.$partnum.'.solved'})) {
- my $status = $resource_data->{'resource.'.$partnum.'.solved'};
- if ($status eq 'correct_by_override') {
- $symbol = '+';
- $sum++;
- } elsif ($status eq 'incorrect_by_override') {
- $symbol = '-';
- } elsif ($status eq 'ungraded_attempted') {
- $symbol = '#';
- } elsif ($status eq 'incorrect_attempted') {
- $symbol = '.';
- } elsif ($status eq 'excused') {
+ $status = $resource_data->{'resource.'.$partnum.'.solved'};
+ }
+ #
+ my $tries = 0;
+ if(exists($resource_data->{'resource.'.$partnum.'.tries'})) {
+ $tries = $resource_data->{'resource.'.$partnum.'.tries'};
+ }
+ #
+ if ($awarded > 0) {
+ # The student has gotten the problem correct to some degree
+ if ($status eq 'excused') {
$symbol = 'x';
$max--;
- } elsif ($status eq 'correct_by_student' &&
- exists($resource_data->{'resource.'.$partnum.'.tries'})){
- $tries = $resource_data->{'resource.'.$partnum.'.tries'};
+ } elsif ($status eq 'correct_by_override') {
+ $symbol = '+';
+ $sum++;
+ } elsif ($tries > 0) {
if ($tries > 9) {
$symbol = '*';
- } elsif ($tries > 0) {
- $symbol = $tries;
} else {
- $symbol = ' ';
+ $symbol = $tries;
}
$sum++;
- } elsif (exists($resource_data->{'resource.'.
- $partnum.'.tries'})){
- $symbol = '.';
} else {
- $symbol = ' ';
+ $symbol = '+';
+ $sum++;
}
} else {
- # Unsolved. Did they try?
- if (exists($resource_data->{'resource.'.$partnum.'.tries'})){
+ # The student has the problem incorrect or it is ungraded
+ if ($status eq 'excused') {
+ $symbol = 'x';
+ $max--;
+ } elsif ($status eq 'incorrect_by_override') {
+ $symbol = '-';
+ } elsif ($status eq 'ungraded_attempted') {
+ $symbol = '#';
+ } elsif ($status eq 'incorrect_attempted' ||
+ $tries > 0) {
$symbol = '.';
} else {
- $symbol = ' ';
+ # Problem is wrong and has not been attempted.
+ $symbol=' ';
}
}
#
@@ -1478,7 +1557,7 @@ sub StudentTriesOnSequence {
$symbol = ''.$symbol.' ';
}
$value .= $symbol;
@@ -1546,11 +1625,15 @@ sub StudentPerformanceOnSequence {
my $awarded = 0;
if (exists($resource_data->{'resource.'.$part.'.awarded'})) {
$awarded = $resource_data->{'resource.'.$part.'.awarded'};
+ $awarded = 0 if (! $awarded);
}
#
$partscore = $weight*$awarded;
$score += $partscore;
- $symbol = $weight;
+ $symbol = $partscore;
+ if (abs($symbol - sprintf("%.0f",$symbol)) < 0.001) {
+ $symbol = sprintf("%.0f",$symbol);
+ }
if (length($symbol) > 1) {
$symbol = '*';
}
@@ -1569,19 +1652,20 @@ sub StudentPerformanceOnSequence {
}
}
#
+ if (! defined($partscore)) {
+ $partscore = $symbol;
+ }
+ push (@ScoreData,$partscore);
+ #
if ( ($links eq 'yes' && $symbol ne ' ') || ($links eq 'all')) {
$symbol = ''.$symbol.' ';
}
- if (! defined($partscore)) {
- $partscore = $symbol;
- }
- push (@ScoreData,$partscore);
+ $Str .= $symbol;
}
- $Str .= $symbol;
}
return ($Str,$performance_length,$score,$max,\@ScoreData);
}