Annotation of loncom/interface/statistics/lonstudentassessment.pm, revision 1.31

1.1       stredwic    1: # The LearningOnline Network with CAPA
                      2: #
1.31    ! matthew     3: # $Id: lonstudentassessment.pm,v 1.30 2003/02/28 21:19:00 matthew Exp $
1.1       stredwic    4: #
                      5: # Copyright Michigan State University Board of Trustees
                      6: #
                      7: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      8: # LON-CAPA is free software; you can redistribute it and/or modify
                      9: # it under the terms of the GNU General Public License as published by
                     10: # the Free Software Foundation; either version 2 of the License, or
                     11: # (at your option) any later version.
                     12: #
                     13: # LON-CAPA is distributed in the hope that it will be useful,
                     14: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     15: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     16: # GNU General Public License for more details.
                     17: #
                     18: # You should have received a copy of the GNU General Public License
                     19: # along with LON-CAPA; if not, write to the Free Software
                     20: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     21: #
                     22: # /home/httpd/html/adm/gpl.txt
                     23: #
                     24: # http://www.lon-capa.org/
                     25: #
                     26: # (Navigate problems for statistical reports
1.28      matthew    27: #
                     28: #######################################################
                     29: #######################################################
                     30: 
                     31: =pod
                     32: 
                     33: =head1 NAME
                     34: 
                     35: lonstudentassessment
                     36: 
                     37: =head1 SYNOPSIS
                     38: 
                     39: Presents assessment data about a student or a group of students.
                     40: 
                     41: =head1 Subroutines
                     42: 
                     43: =over 4 
                     44: 
                     45: =cut
                     46: 
                     47: #######################################################
                     48: #######################################################
1.1       stredwic   49: 
1.21      minaeibi   50: package Apache::lonstudentassessment;
1.1       stredwic   51: 
                     52: use strict;
1.28      matthew    53: use Apache::lonstatistics;
1.1       stredwic   54: use Apache::lonhtmlcommon;
                     55: use Apache::loncoursedata;
1.28      matthew    56: use Apache::lonnet; # for logging porpoises
1.31    ! matthew    57: use Spreadsheet::WriteExcel;
        !            58: 
        !            59: #######################################################
        !            60: #######################################################
        !            61: =pod
        !            62: 
        !            63: =item Package Variables
        !            64: 
        !            65: =over 4
        !            66: 
        !            67: =item $Statistics Hash ref to store student data.  Indexed by symb,
        !            68:       contains hashes with keys 'score' and 'max'.
        !            69: 
        !            70: =cut
        !            71: 
        !            72: #######################################################
        !            73: #######################################################
1.1       stredwic   74: 
1.30      matthew    75: my $Statistics;
                     76: 
1.28      matthew    77: #######################################################
                     78: #######################################################
                     79: 
                     80: =pod
                     81: 
1.31    ! matthew    82: =item $show_links 'yes' or 'no' for linking to student performance data
        !            83: 
        !            84: =item $output_mode 'html', 'excel', or 'csv' for output mode
        !            85: 
        !            86: =item $show 'all' or 'totals' determines how much data is output
        !            87: 
        !            88: =cut
        !            89: 
        !            90: #######################################################
        !            91: #######################################################
        !            92: my $show_links;
        !            93: my $output_mode;
        !            94: my $show;
1.28      matthew    95: 
1.31    ! matthew    96: #######################################################
        !            97: #######################################################
        !            98: # End of package variable declarations
1.28      matthew    99: 
1.31    ! matthew   100: =pod
1.28      matthew   101: 
1.31    ! matthew   102: =back
1.28      matthew   103: 
1.31    ! matthew   104: =cut
1.28      matthew   105: 
1.31    ! matthew   106: #######################################################
        !           107: #######################################################
1.28      matthew   108: 
1.31    ! matthew   109: =pod
1.28      matthew   110: 
1.31    ! matthew   111: =item &BuildStudentAssessmentPage()
1.28      matthew   112: 
1.31    ! matthew   113: Inputs: 
1.4       stredwic  114: 
1.31    ! matthew   115: =over 4
1.28      matthew   116: 
                    117: =item $r Apache Request
                    118: 
                    119: =item $c Apache Connection 
                    120: 
                    121: =back
                    122: 
                    123: =cut
                    124: 
                    125: #######################################################
                    126: #######################################################
1.1       stredwic  127: sub BuildStudentAssessmentPage {
1.30      matthew   128:     my ($r,$c)=@_;
                    129:     undef($Statistics);
                    130:     #
1.31    ! matthew   131:     # Print out the HTML headers for the interface
        !           132:     #    This also parses the output mode selector
        !           133:     #    This step must always be done.
1.30      matthew   134:     $r->print(&CreateInterface());
1.31    ! matthew   135:     $r->print('<input type="hidden" name="notfirstrun" value="true" />');
1.7       stredwic  136:     $r->rflush();
1.31    ! matthew   137:     if (! exists($ENV{'form.notfirstrun'})) {
        !           138:         $r->print(<<ENDMSG);
        !           139: <p>
        !           140: <font size="+1">
        !           141: Please make your selections in the boxes above and hit 
        !           142: the button marked &quot;Update&nbsp;Display&quot;.
        !           143: </font>
        !           144: </p>
        !           145: ENDMSG
        !           146:         return;
        !           147:     }
        !           148:     #
        !           149:     #
        !           150:     my $initialize     = \&html_initialize;
        !           151:     my $output_student = \&html_outputstudent;
        !           152:     my $finish         = \&html_finish;
        !           153:     #
        !           154:     if ($output_mode eq 'excel') {
        !           155:         $initialize     = \&excel_initialize;
        !           156:         $output_student = \&excel_outputstudent;
        !           157:         $finish         = \&excel_finish;
        !           158:     } elsif ($output_mode eq 'csv') {
        !           159:         $initialize     = \&csv_initialize;
        !           160:         $output_student = \&csv_outputstudent;
        !           161:         $finish         = \&csv_finish;
        !           162:     }
1.30      matthew   163:     #
                    164:     if($c->aborted()) {  return ; }
1.31    ! matthew   165:     #
        !           166:     # Call the initialize routine selected above
        !           167:     $initialize->($r);
1.30      matthew   168:     foreach my $student (@Apache::lonstatistics::Students) {
1.31    ! matthew   169:         if($c->aborted()) { 
        !           170:             $finish->($r);
        !           171:             return ; 
1.1       stredwic  172:         }
1.31    ! matthew   173:         # Call the output_student routine selected above
        !           174:         $output_student->($r,$student);
        !           175:     }
        !           176:     # Call the "finish" routine selected above
        !           177:     $finish->($r);
        !           178:     #
        !           179:     return;
        !           180: }
        !           181: 
        !           182: #######################################################
        !           183: #######################################################
1.30      matthew   184: 
1.31    ! matthew   185: sub get_student_fields_to_show {
        !           186:     my @to_show = @Apache::lonstatistics::SelectedStudentData;
        !           187:     foreach (@to_show) {
        !           188:         if ($_ eq 'all') {
        !           189:             @to_show = @Apache::lonstatistics::StudentDataOrder;
        !           190:             last;
        !           191:         }
        !           192:     }
        !           193:     return @to_show;
        !           194: }
        !           195: 
        !           196: sub get_sequences_to_show {
        !           197:     my @Sequences;
        !           198:     foreach my $map_symb (@Apache::lonstatistics::SelectedMaps) {
        !           199:         foreach my $sequence (@Apache::lonstatistics::Sequences) {
        !           200:             next if ($sequence->{'symb'} ne $map_symb && $map_symb ne 'all');
        !           201:             next if ($sequence->{'num_assess'} < 1);
        !           202:             push (@Sequences,$sequence);
        !           203:         }
1.1       stredwic  204:     }
1.31    ! matthew   205:     return @Sequences;
1.2       stredwic  206: }
1.30      matthew   207: 
1.31    ! matthew   208: 
1.28      matthew   209: #######################################################
                    210: #######################################################
                    211: 
                    212: =pod
1.2       stredwic  213: 
1.28      matthew   214: =item &CreateInterface()
1.21      minaeibi  215: 
1.28      matthew   216: Called by &BuildStudentAssessmentPage to create the top part of the
                    217: page which displays the chart.
                    218: 
1.30      matthew   219: Inputs: None
1.28      matthew   220: 
                    221: Returns:  A string containing the HTML for the headers and top table for 
                    222: the chart page.
                    223: 
                    224: =cut
                    225: 
                    226: #######################################################
                    227: #######################################################
1.2       stredwic  228: sub CreateInterface {
1.4       stredwic  229:     my $Str = '';
1.30      matthew   230: #    $Str .= &CreateLegend();
                    231:     $Str .= '<table cellspacing="5">'."\n";
                    232:     $Str .= '<tr>';
                    233:     $Str .= '<td align="center"><b>Sections</b></td>';
                    234:     $Str .= '<td align="center"><b>Student Data</b></td>';
                    235:     $Str .= '<td align="center"><b>Sequences and Folders</b></td>';
1.31    ! matthew   236:     $Str .= '<td align="center"><b>Output Format</b></td>';
1.30      matthew   237:     $Str .= '</tr>'."\n";
                    238:     #
1.4       stredwic  239:     $Str .= '<tr><td align="center">'."\n";
1.29      matthew   240:     $Str .= &Apache::lonstatistics::SectionSelect('Section','multiple',5);
1.4       stredwic  241:     $Str .= '</td><td align="center">';
1.30      matthew   242:     my $only_seq_with_assessments = sub { 
                    243:         my $s=shift;
                    244:         if ($s->{'num_assess'} < 1) { 
                    245:             return 0;
                    246:         } else { 
                    247:             return 1;
                    248:         }
                    249:     };
                    250:     $Str .= &Apache::lonstatistics::StudentDataSelect('StudentData','multiple',
                    251:                                                       5,undef);
1.4       stredwic  252:     $Str .= '</td><td>'."\n";
1.30      matthew   253:     $Str .= &Apache::lonstatistics::MapSelect('Maps','multiple,all',5,
                    254:                                               $only_seq_with_assessments);
1.31    ! matthew   255:     $Str .= '</td><td>'."\n";
        !           256:     $Str .= &CreateAndParseOutputSelector();
1.30      matthew   257:     $Str .= '</td></tr>'."\n";
                    258:     $Str .= '</table>'."\n";
1.4       stredwic  259:     return $Str;
1.1       stredwic  260: }
1.30      matthew   261: 
                    262: #######################################################
                    263: #######################################################
                    264: 
                    265: =pod
                    266: 
1.31    ! matthew   267: =item &CreateAndParseOutputSelector()
1.30      matthew   268: 
                    269: =cut
                    270: 
                    271: #######################################################
                    272: #######################################################
1.31    ! matthew   273: sub CreateAndParseOutputSelector {
        !           274:     my $Str = '';
        !           275:     my $elementname = 'outputmode';
        !           276:     #
        !           277:     # Format for output options is 'mode, restrictions';
        !           278:     my @Options = ('html, with links','html, without links',
        !           279:                    'html, totals only','excel, totals only',
        !           280:                    'csv, totals only','csv, everything');
        !           281:     my $selected = 'html, with links';
        !           282:     if (exists($ENV{'form.'.$elementname})) {
        !           283:         if (ref($ENV{'form.'.$elementname} eq 'ARRAY')) {
        !           284:             $selected = $ENV{'form.'.$elementname}->[0];
        !           285:         } else {
        !           286:             $selected = $ENV{'form.'.$elementname};
        !           287:         }
        !           288:     }
        !           289:     #
        !           290:     # Set package variables describing output mode
        !           291:     $show_links  = 'no';
        !           292:     $output_mode = 'html';
        !           293:     $show        = 'all';
        !           294:     my ($mode,$restriction) = split(',',$selected);
        !           295:     $restriction =~ s/^\s*//;
        !           296:     if ($mode =~ /^(html|excel|csv)$/) {
        !           297:         $output_mode = $mode;
        !           298:     } else {
        !           299:         $output_mode = 'html';
        !           300:     }
        !           301:     if ($restriction eq 'with links') {
        !           302:         $show_links = 'yes';
        !           303:     } else {
        !           304:         $show_links = 'no';
        !           305:     }
        !           306:     if ($restriction eq 'totals only') {
        !           307:         $show = 'totals';
        !           308:     } else {
        !           309:         $show = 'everything';
        !           310:     }
        !           311:     #
        !           312:     # Build the form element
        !           313:     $Str = qq/<select size="5" name="$elementname">/;
        !           314:     foreach my $option (@Options) {
        !           315:         $Str .= qq/\n    <option value="$option"/;
        !           316:         $Str .= " selected " if ($option eq $selected);
        !           317:         $Str .= ">$option<\/option>";
        !           318:     }
        !           319:     $Str .= "\n</select>";
        !           320:     return $Str;
        !           321: }
1.30      matthew   322: 
1.28      matthew   323: #######################################################
                    324: #######################################################
1.1       stredwic  325: 
1.28      matthew   326: =pod
                    327: 
1.31    ! matthew   328: =head2 HTML output routines
1.28      matthew   329: 
1.31    ! matthew   330: =item &html_initialize($r)
1.28      matthew   331: 
1.31    ! matthew   332: Create labels for the columns of student data to show.
1.28      matthew   333: 
1.31    ! matthew   334: =item &html_outputstudent($r,$student)
1.28      matthew   335: 
1.31    ! matthew   336: Return a line of the chart for a student.
1.28      matthew   337: 
1.31    ! matthew   338: =item &html_finish($r)
1.28      matthew   339: 
                    340: =cut
                    341: 
                    342: #######################################################
                    343: #######################################################
1.31    ! matthew   344: {
        !           345:     my $padding;
        !           346:     my $count;
        !           347: 
        !           348: sub html_initialize {
        !           349:     my ($r) = @_;
1.30      matthew   350:     #
                    351:     $padding = ' 'x3;
1.31    ! matthew   352:     $count = 1;
1.30      matthew   353:     #
1.31    ! matthew   354:     my $Str = "<pre>\n";
1.30      matthew   355:     # First, the @StudentData fields need to be listed
1.31    ! matthew   356:     my @to_show = &get_student_fields_to_show();
1.30      matthew   357:     foreach my $field (@to_show) {
                    358:         my $title=$Apache::lonstatistics::StudentData{$field}->{'title'};
                    359:         my $base =$Apache::lonstatistics::StudentData{$field}->{'base_width'};
                    360:         my $width=$Apache::lonstatistics::StudentData{$field}->{'width'};
                    361:         $Str .= $title.' 'x($width-$base).$padding;
                    362:     }
                    363:     # Now the selected sequences need to be listed
1.31    ! matthew   364:     foreach my $sequence (&get_sequences_to_show) {
        !           365:         my $title = $sequence->{'title'};
        !           366:         my $base  = $sequence->{'base_width'};
        !           367:         my $width = $sequence->{'width'};
        !           368:         $Str .= $title.' 'x($width-$base).$padding;
1.30      matthew   369:     }
1.31    ! matthew   370:     $Str .= "total (of shown problems)</pre>\n";
        !           371:     $Str .= "<pre>";
        !           372:     $r->print($Str);
        !           373:     $r->rflush();
        !           374:     return;
1.30      matthew   375: }
                    376: 
1.31    ! matthew   377: sub html_outputstudent {
        !           378:     my ($r,$student) = @_;
1.2       stredwic  379:     my $Str = '';
1.30      matthew   380:     # First, the @StudentData fields need to be listed
1.31    ! matthew   381:     my @to_show = &get_student_fields_to_show();
1.30      matthew   382:     foreach my $field (@to_show) {
                    383:         my $title=$student->{$field};
1.31    ! matthew   384:         my $base = length($title);
1.30      matthew   385:         my $width=$Apache::lonstatistics::StudentData{$field}->{'width'};
                    386:         $Str .= $title.' 'x($width-$base).$padding;
                    387:     }
                    388:     # Get ALL the students data
                    389:     my %StudentsData;
                    390:     my @tmp = &Apache::loncoursedata::get_current_state
                    391:         ($student->{'username'},$student->{'domain'},undef,
                    392:          $ENV{'request.course.id'});
                    393:     if ((scalar @tmp > 0) && ($tmp[0] !~ /^error:/)) {
                    394:         %StudentsData = @tmp;
                    395:     }
                    396:     if (scalar(@tmp) < 1) {
                    397:         $Str .= '<font color="blue">No Course Data</font>'."\n";
1.31    ! matthew   398:         $r->print($Str);
        !           399:         $r->rflush();
        !           400:         return;
1.30      matthew   401:     }
                    402:     #
                    403:     # By sequence build up the data
                    404:     my $studentstats;
1.31    ! matthew   405:     my $PerformanceStr = '';
        !           406:     foreach my $seq (&get_sequences_to_show) {
        !           407:         my ($performance,$score,$seq_max) =
        !           408:             &StudentPerformanceOnSequence($student,\%StudentsData,
        !           409:                                           $seq,$show_links);
        !           410:         my $ratio = $score.'/'.$seq_max;
        !           411:         #
        !           412:         if ($show eq 'totals') {
        !           413:             $performance = ' 'x(length($seq_max)-length($score)).$ratio;
        !           414:             $performance .= ' 'x($seq->{'width'}-length($performance));
        !           415:         } else {
        !           416:             # Pad with extra spaces
        !           417:             $performance .= ' 'x($seq->{'width'}-$seq_max-
        !           418:                                  length($ratio)
        !           419:                                  ).$ratio;
1.30      matthew   420:         }
1.31    ! matthew   421:         #
        !           422:         $Str .= $performance.$padding;
        !           423:         #
        !           424:         $studentstats->{$seq->{'symb'}}->{'score'}= $score;
        !           425:         $studentstats->{$seq->{'symb'}}->{'max'}  = $seq_max;
1.30      matthew   426:     }
                    427:     #
                    428:     # Total it up and store the statistics info.
                    429:     my ($score,$max) = (0,0);
                    430:     while (my ($symb,$seq_stats) = each (%{$studentstats})) {
                    431:         $Statistics->{$symb}->{'score'} += $seq_stats->{'score'};
                    432:         $Statistics->{$symb}->{'max'}   += $seq_stats->{'max'};
                    433:         $score += $seq_stats->{'score'};
                    434:         $max   += $seq_stats->{'max'};
                    435:     }
1.31    ! matthew   436:     $Str .= ' '.' 'x(length($max)-length($score)).$score.'/'.$max;
1.30      matthew   437:     $Str .= " \n";
1.31    ! matthew   438:     $r->print($Str);
        !           439:     #
        !           440:     $count++;
        !           441:     if($count % 5 == 0) {
        !           442:         $r->print("</pre><pre>");
        !           443:     }
        !           444:     #
        !           445:     $r->rflush();
        !           446:     return;
1.30      matthew   447: }    
1.2       stredwic  448: 
1.31    ! matthew   449: sub html_finish {
        !           450:     my ($r) = @_;
        !           451:     $r->print("</pre>\n"); 
        !           452:     $r->rflush();
        !           453:     return;
        !           454: }
        !           455: 
        !           456: }
        !           457: 
        !           458: #######################################################
        !           459: #######################################################
        !           460: 
        !           461: =pod
        !           462: 
        !           463: =head2 EXCEL subroutines
        !           464: 
        !           465: =item &excel_initialize($r)
        !           466: 
        !           467: =item &excel_outputstudent($r,$student)
        !           468: 
        !           469: =item &excel_finish($r)
        !           470: 
        !           471: =cut
        !           472: 
        !           473: #######################################################
        !           474: #######################################################
        !           475: {
        !           476: 
        !           477: my $excel_sheet;
        !           478: 
        !           479: sub excel_initialize {
        !           480:     my ($r) = @_;
        !           481:     #
        !           482:     $r->print("<h1>Not implemented yet</h1>");
        !           483:     return;
        !           484:     my $filename = '/prtspool/'.
        !           485:         $ENV{'user.name'}.'_'.$ENV{'user.domain'}.'_'.
        !           486:             time.'_'.rand(1000000000).'.xls';
        !           487:     $excel_sheet = Spreadsheet::WriteExcel->new('/home/httpd'.$filename);
        !           488:     if (! defined($excel_sheet)) {
        !           489:         $r->log_error("Error creating excel spreadsheet $filename: $!");
        !           490:         $r->print("Problems creating new Excel file.  ".
        !           491:                   "This error has been logged.  ".
        !           492:                   "Please alert your LON-CAPA administrator");
        !           493:         return 0;
        !           494:     }
        !           495:     #
        !           496:     # The excel spreadsheet stores temporary data in files, then put them
        !           497:     # together.  If needed we should be able to disable this (memory only).
        !           498:     # The temporary directory must be specified before calling 'addworksheet'.
        !           499:     # File::Temp is used to determine the temporary directory.
        !           500:     $excel_sheet->set_tempdir($Apache::lonnet::tmpdir);
        !           501:     #
        !           502:     # Determine the name to give the worksheet
        !           503: #    $excel_sheet->addworksheet();
        !           504: 
        !           505:     return;
        !           506: }
        !           507: 
        !           508: sub excel_outputstudent {
        !           509:     my ($r,$student) = @_;
        !           510: }
        !           511: 
        !           512: sub excel_finish {
        !           513:     my ($r) = @_;
        !           514: }
        !           515: 
        !           516: }
1.30      matthew   517: #######################################################
                    518: #######################################################
                    519: 
                    520: =pod
                    521: 
1.31    ! matthew   522: =head2 CSV output routines
        !           523: 
        !           524: =item &csv_initialize($r)
        !           525: 
        !           526: =item &csv_outputstudent($r,$student)
        !           527: 
        !           528: =item &csv_finish($r)
1.30      matthew   529: 
                    530: =cut
                    531: 
                    532: #######################################################
                    533: #######################################################
1.31    ! matthew   534: {
        !           535: 
        !           536: sub csv_initialize{
        !           537:     my ($r) = @_;
        !           538:     $r->print("<h1>Not implemented yet</h1>");
        !           539:     return;
        !           540: }
        !           541: 
        !           542: sub csv_outputstudent {
        !           543:     my ($r,$student) = @_;
        !           544: }
        !           545: 
        !           546: sub csv_finish {
        !           547:     my ($r) = @_;
        !           548: }
1.2       stredwic  549: 
                    550: }
                    551: 
1.28      matthew   552: #######################################################
                    553: #######################################################
                    554: 
1.2       stredwic  555: =pod
                    556: 
1.30      matthew   557: =item &StudentPerformanceOnSequence()
1.2       stredwic  558: 
1.30      matthew   559: Inputs:
1.2       stredwic  560: 
                    561: =over 4
                    562: 
1.30      matthew   563: =item $student
1.28      matthew   564: 
1.30      matthew   565: =item $studentdata Hash ref to all student data
1.2       stredwic  566: 
1.30      matthew   567: =item $seq Hash ref, the sequence we are working on
1.2       stredwic  568: 
1.30      matthew   569: =item $links if defined we will output links to each resource.
1.2       stredwic  570: 
1.28      matthew   571: =back
1.2       stredwic  572: 
                    573: =cut
1.1       stredwic  574: 
1.28      matthew   575: #######################################################
                    576: #######################################################
1.30      matthew   577: sub StudentPerformanceOnSequence {
1.31    ! matthew   578:     my ($student,$studentdata,$seq,$links,$totalonly) = @_;
        !           579:     $totalonly = 0 if (! defined($totalonly));
        !           580:     $links = 'no' if (! defined($links));
1.1       stredwic  581:     my $Str = '';
1.30      matthew   582:     my ($sum,$max) = (0,0);
                    583:     foreach my $resource (@{$seq->{'contents'}}) {
                    584:         next if ($resource->{'type'} ne 'assessment');
                    585:         my $resource_data = $studentdata->{$resource->{'symb'}};
                    586:         my $value = '';
                    587:         foreach my $partnum (@{$resource->{'parts'}}) {
                    588:             $max++;
                    589:             my $symbol = ' '; # default to space
                    590:             #
                    591:             if (exists($resource_data->{'resource.'.$partnum.'.solved'})) {
                    592:                 my $status = $resource_data->{'resource.'.$partnum.'.solved'};
                    593:                 if ($status eq 'correct_by_override') {
                    594:                     $symbol = '+';
                    595:                     $sum++;
                    596:                 } elsif ($status eq 'incorrect_by_override') {
                    597:                     $symbol = '-';
                    598:                 } elsif ($status eq 'ungraded_attempted') {
                    599:                     $symbol = '#';
                    600:                 } elsif ($status eq 'incorrect_attempted')  {
                    601:                     $symbol = '.';
                    602:                 } elsif ($status eq 'excused') {
                    603:                     $symbol = 'x';
                    604:                     $max--;
                    605:                 } elsif ($status eq 'correct_by_student' &&
                    606:                     exists($resource_data->{'resource.'.$partnum.'.tries'})){
                    607:                     my $num = $resource_data->{'resource.'.$partnum.'.tries'};
                    608:                     if ($num > 9) {
                    609:                         $symbol = '*';
                    610:                     } elsif ($num > 0) {
                    611:                         $symbol = $num;
                    612:                     } else {
                    613:                         $symbol = ' ';
                    614:                     }
                    615:                     $sum++;
                    616:                 } else {
                    617:                     $symbol = ' ';
1.2       stredwic  618:                 }
1.30      matthew   619:             } else {
                    620:                 # Unsolved.  Did they try?
                    621:                 if (exists($resource_data->{'resource.'.$partnum.'.tries'})){
                    622:                     $symbol = '.';
                    623:                 } else {
                    624:                     $symbol = ' ';
1.18      matthew   625:                 }
1.2       stredwic  626:             }
1.30      matthew   627:             #
1.31    ! matthew   628:             if ($links eq 'yes' && $symbol ne ' ') {
1.30      matthew   629:                 $symbol = '<a href="/adm/grades'.
                    630:                     '?symb='.&Apache::lonnet::escape($resource->{'symb'}).
                    631:                         '&student='.$student->{'username'}.
                    632:                             '&domain='.$student->{'domain'}.
                    633:                                 '&command=submission">'.$symbol.'</a>';
                    634:             }
                    635:             $value .= $symbol;
1.2       stredwic  636:         }
1.30      matthew   637:         $Str .= $value;
1.17      minaeibi  638:     }
1.30      matthew   639:     return ($Str,$sum,$max);
1.17      minaeibi  640: }
                    641: 
1.28      matthew   642: #######################################################
                    643: #######################################################
1.17      minaeibi  644: sub StudentAverageTotal {
1.21      minaeibi  645:     my ($cache, $students, $sequenceKeys)=@_;
1.23      minaeibi  646:     my $Str = "\n<b>Summary Tables:</b>\n";
1.21      minaeibi  647:     my %Correct = ();
                    648:     my $ProblemsSolved = 0;
                    649:     my $TotalProblems = 0;
                    650:     my $StudentCount = 0;
                    651: 
                    652:     foreach my $name (@$students) {
                    653:         $StudentCount++;
                    654:         foreach my $sequence (@$sequenceKeys) {
1.23      minaeibi  655:             $Correct{$sequence} +=
                    656: 	       $cache->{$name.':'.$sequence.':problemsCorrect'};
1.17      minaeibi  657:         }
1.21      minaeibi  658: 	$ProblemsSolved += $cache->{$name.':problemsSolved'};
                    659:         $TotalProblems += $cache->{$name.':totalProblems'};
1.1       stredwic  660:     }
1.25      matthew   661:     if ($StudentCount) { 
1.27      minaeibi  662:         $ProblemsSolved = sprintf( "%.2f", 
                    663:                              $ProblemsSolved/$StudentCount);
1.25      matthew   664:         $TotalProblems /= $StudentCount;
                    665:     } else {
                    666:         $ProblemsSolved = 0;
                    667:         $TotalProblems  = 0;
                    668:     }
1.27      minaeibi  669: 
1.24      minaeibi  670:     $Str .= '<table border=2 cellspacing="1">'."\n";
1.23      minaeibi  671:     $Str .= '<tr><td><b>Students Count</b></td><td><b>'.
                    672:             $StudentCount.'</b></td></tr>'."\n";
                    673:     $Str .= '<tr><td><b>Total Problems</b></td><td><b>'.
                    674:             $TotalProblems.'</b></td></tr>'."\n";
                    675:     $Str .= '<tr><td><b>Average Correct</b></td><td><b>'.
                    676:             $ProblemsSolved.'</b></td></tr>'."\n";
                    677:     $Str .= '</table>'."\n";
                    678: 
1.24      minaeibi  679:     $Str .= '<table border=2 cellspacing="1">'."\n";
1.23      minaeibi  680:     $Str .= '<tr><th>Title</th><th>Total Problems</th>'.
                    681:             '<th>Average Correct</th></tr>'."\n";
                    682:     foreach my $S(@$sequenceKeys) {
                    683:         my $title=$cache->{$S.':title'};
                    684: 	#$Str .= $cache->{$S.':problems'};
1.24      minaeibi  685: 	#my @problems=split(':', $cache->{$S.':problems'});
1.23      minaeibi  686: 	#my $pCount=scalar @problems;
                    687: 	my $pCount=MaxSeqPr($cache,@$students[0],$S);
1.25      matthew   688:         my $crr;
                    689: 	if ($StudentCount) {
                    690:             $crr=sprintf( "%.2f", $Correct{$S}/$StudentCount );
                    691:         } else {
                    692:             $crr="0.00";
                    693:         }
1.23      minaeibi  694:         $Str .= '<tr><td>'.$title.
                    695:                 '</td><td align=center>'.$pCount.
                    696:                 '</td><td align=center>'.$crr.
                    697:                 '</td></tr>'."\n";
1.10      stredwic  698:     }
1.1       stredwic  699: 
1.23      minaeibi  700:     $Str .= '</table>'."\n";
                    701: 
1.1       stredwic  702:     return $Str;
                    703: }
1.23      minaeibi  704: 
1.28      matthew   705: #######################################################
                    706: #######################################################
1.23      minaeibi  707: 
1.2       stredwic  708: =pod
                    709: 
                    710: =item &CreateLegend()
                    711: 
                    712: This function returns a formatted string containing the legend for the
                    713: chart.  The legend describes the symbols used to represent grades for
                    714: problems.
                    715: 
                    716: =cut
                    717: 
1.28      matthew   718: #######################################################
                    719: #######################################################
1.2       stredwic  720: sub CreateLegend {
                    721:     my $Str = "<p><pre>".
1.13      minaeibi  722:               "   1  correct by student in 1 try\n".
                    723:               "   7  correct by student in 7 tries\n".
1.12      minaeibi  724:               "   *  correct by student in more than 9 tries\n".
1.20      minaeibi  725: 	      "   +  correct by hand grading or override\n".
1.12      minaeibi  726:               "   -  incorrect by override\n".
                    727: 	      "   .  incorrect attempted\n".
                    728: 	      "   #  ungraded attempted\n".
1.13      minaeibi  729:               "      not attempted (blank field)\n".
1.12      minaeibi  730: 	      "   x  excused".
1.17      minaeibi  731:               "</pre><p>";
1.2       stredwic  732:     return $Str;
                    733: }
                    734: 
1.28      matthew   735: #######################################################
                    736: #######################################################
                    737: 
1.30      matthew   738: =pod 
1.2       stredwic  739: 
                    740: =back
                    741: 
                    742: =cut
                    743: 
1.28      matthew   744: #######################################################
                    745: #######################################################
1.2       stredwic  746: 
1.28      matthew   747: 1;
1.2       stredwic  748: 
1.1       stredwic  749: __END__

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>