Diff for /loncom/interface/lonquickgrades.pm between versions 1.96 and 1.104

version 1.96, 2011/06/01 20:32:30 version 1.104, 2014/05/20 20:32:16
Line 29 Line 29
 package Apache::lonquickgrades;  package Apache::lonquickgrades;
   
 use strict;  use strict;
 use Apache::Constants qw(:common :http);  use Apache::Constants qw(:common :http REDIRECT);
 use POSIX;  use POSIX;
 use Apache::loncommon;  use Apache::loncommon;
 use Apache::lonlocal;  use Apache::lonlocal;
 use Apache::lonnet;  use Apache::lonnet;
 use Apache::grades;  use Apache::grades;
   use Apache::loncoursedata;
   use Apache::lonstudentassessment;
   
   use Time::HiRes;
   use Spreadsheet::WriteExcel;
   use Spreadsheet::WriteExcel::Utility();
   #
   # Excel data
   #
   my $excel_sheet;
   my $excel_workbook;
   my $filename;
   my $format;
   my $request_aborted;
   my $header_row;
   my $cols_output;
   my %prog_state;
   
   
 sub handler {  sub handler {
     my $r = shift;      my $r = shift;
Line 44  sub handler { Line 62  sub handler {
 sub real_handler {  sub real_handler {
     my $r = shift;      my $r = shift;
   
       # Check for critical messages and redirect if present.  
       my ($redirect,$url) = &Apache::loncommon::critical_redirect(300);
       if ($redirect) {
           &Apache::loncommon::content_type($r,'text/html');
           $r->header_out(Location => $url);
           return REDIRECT;
       }
   
     &Apache::loncommon::get_unprocessed_cgi($ENV{QUERY_STRING});      &Apache::loncommon::get_unprocessed_cgi($ENV{QUERY_STRING});
   
     # Handle header-only request      # Handle header-only request
Line 89  sub real_handler { Line 115  sub real_handler {
     my $udom;      my $udom;
     my $stdid;      my $stdid;
     if ($cangrade) {      if ($cangrade) {
           $r->print("<h2>".&mt("Download Multiple")."</h2>".
                     '<table cellspacing="5">'."\n".
                     '<tr>'.
                     '<td align="center"><b>'.&mt('Sections').'</b>'.
                     &Apache::loncommon::help_open_topic("Chart_Sections").
                     '</td>'.
                     '<td align="center"><b>'.&mt('Groups').'</b>'.
                     '</td>'.
                     '<td align="center"><b>'.&mt('Student Data').'</b>'.
                     &Apache::loncommon::help_open_topic("Chart_Student_Data").
                     '</td>'.
                     '<td align="center"><b>'.&mt('Access Status').'</b>'.
                     &Apache::loncommon::help_open_topic("Chart_Enrollment_Status").
                     '</td>'.
                     '<td align="center"><b>'.&mt('Output Format').'</b>'.
                     &Apache::loncommon::help_open_topic("Chart_Output_Formats").
                     '</td><td>&nbsp;</td></tr>'."\n".
                     '<tr><td align="center">'."\n".
                     &Apache::lonstatistics::SectionSelect('Section','multiple',5).
                     '</td><td align="center">'.
                     &Apache::lonstatistics::GroupSelect('Group','multiple',5).
                     '</td><td align="center">'.
                     &Apache::lonstatistics::StudentDataSelect('StudentData','multiple',5,undef).
                     '</td><td>'."\n".
                     &Apache::lonhtmlcommon::StatusOptions(undef,undef,5).
                     '</td><td>'."\n".
                     &Apache::lonstudentassessment::CreateAndParseOutputSelector().
                     '</td><td>'.
                     '<input type="submit" name="download" value="'.&mt('Display/Download Multiple Students').'" />'.
                     '</td></tr>'."\n".
                     '</table>'."\n"
                    );
           $r->print("<hr /><h2>".&mt("Display Individual")."</h2>");
         if ($env{'form.uname'}) { $uname=$env{'form.uname'}; }          if ($env{'form.uname'}) { $uname=$env{'form.uname'}; }
         if ($env{'form.udom'}) { $udom=$env{'form.udom'}; }          if ($env{'form.udom'}) { $udom=$env{'form.udom'}; }
         if ($env{'form.id'}) { $stdid=$env{'form.id'}; }          if ($env{'form.id'}) { $stdid=$env{'form.id'}; }
Line 106  sub real_handler { Line 165  sub real_handler {
         $r->print(&mt('For User [_1] or Student/Employee ID [_2] at Domain [_3]'          $r->print(&mt('For User [_1] or Student/Employee ID [_2] at Domain [_3]'
                  ,'<input type="text" value="'.$uname.'" size="12" name="uname" />'                   ,'<input type="text" value="'.$uname.'" size="12" name="uname" />'
                  ,'<input type="text" value="'.$stdid.'" size="12" name="id" /> '                   ,'<input type="text" value="'.$stdid.'" size="12" name="id" /> '
                  ,$chooseopt).'<br />'.                   ,$chooseopt).
                  '<input type="submit" name="display" value="'.&mt('Update Display').'" /></p>');                   '&nbsp;&nbsp;<input type="submit" name="display" value="'.&mt('Display Individual Student').'" /></p>');
         if (($uname) && ($udom)) {          if (($uname) && ($udom)) {
             $r->print('<p>'.&mt('Full Name: [_1]',&Apache::loncommon::plainname($uname,$udom)).'</p>');              $r->print('<p>'.&mt('Full Name: [_1]',&Apache::loncommon::plainname($uname,$udom)).'</p>');
         }          }
Line 130  sub real_handler { Line 189  sub real_handler {
   
 }  }
   
   sub getStudentCatGrade {
       my ($uname,$udom,%categories)=@_;
       my ($navmap,$totalParts,$totalPossible,$totalRight,$totalAttempted,$topLevelParts,$topLevelRight,$topLevelAttempted)=
          &getData(1,$uname,$udom);
       return &output_category_table(undef,0,$navmap,0,%categories);
   }
   
   sub getAllStudentData {
       my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
       my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
   
       my %categories=&Apache::lonnet::dump('grading_categories',$cdom,$cnum);
   
       my $classlist = &Apache::loncoursedata::get_classlist();
   
       my $statusidx   = &Apache::loncoursedata::CL_STATUS();
       my $usernameidx = &Apache::loncoursedata::CL_SNAME();
       my $domainidx   = &Apache::loncoursedata::CL_SDOM();
       my $fullnameidx = &Apache::loncoursedata::CL_FULLNAME();
   
       foreach my $key (keys(%{$classlist})) {
           my $student = $classlist->{$key};
           my $perc=&getStudentCatGrade($classlist->{$student}->[$usernameidx],
                                        $classlist->{$student}->[$domainidx],
                                        %categories);
       }
   }
   
   
 sub startGradeScreen {  sub startGradeScreen {
     my ($r,$mode)=@_;      my ($r,$mode)=@_;
   
Line 181  sub startGradeScreen { Line 269  sub startGradeScreen {
        if ($env{'form.symb'}) {         if ($env{'form.symb'}) {
           $r->print("\n".'<li'.($mode eq 'probgrading'?' class="active"':'').'><a href="/adm/grades?symb='.            $r->print("\n".'<li'.($mode eq 'probgrading'?' class="active"':'').'><a href="/adm/grades?symb='.
                                               &Apache::lonhtmlcommon::entity_encode($env{'form.symb'}).                                                &Apache::lonhtmlcommon::entity_encode($env{'form.symb'}).
                                               '&command=gradingmenu"><b>&nbsp;&nbsp;&nbsp;&nbsp;'.                                                '&amp;command=gradingmenu"><b>&nbsp;&nbsp;&nbsp;&nbsp;'.
                                               &mt('Problem Grading').'&nbsp;&nbsp;&nbsp;&nbsp;</b></a></li>');                                                &mt('Problem Grading').'&nbsp;&nbsp;&nbsp;&nbsp;</b></a></li>');
   
        }         }
Line 195  sub endGradeScreen { Line 283  sub endGradeScreen {
    $r->print('</div></div></div>'.&Apache::loncommon::end_page());     $r->print('</div></div></div>'.&Apache::loncommon::end_page());
 }  }
   
   # -----------
   
   
   sub excel_cleanup {
       undef ($excel_sheet);
       undef ($excel_workbook);
       undef ($filename);
       undef ($format);
   }
   
   
   sub excel_initialize {
       my ($r) = @_;
   
       &excel_cleanup();
   
       # Create sheet
       ($excel_workbook,$filename,$format)=
           &Apache::loncommon::create_workbook($r);
       return if (! defined($excel_workbook));
      #
      # Add a worksheet
       my $sheetname = $env{'course.'.$env{'request.course.id'}.'.description'};
       $sheetname = &Apache::loncommon::clean_excel_name($sheetname);
       $excel_sheet = $excel_workbook->addworksheet($sheetname);
      #
      # Put the course description in the header
       $excel_sheet->write($header_row,$cols_output++,
                      $env{'course.'.$env{'request.course.id'}.'.description'},
                           $format->{'h1'});
   } 
   
   sub excel_finish {
       my ($r) = @_;
       if ($request_aborted || ! defined($excel_sheet)) {
           &excel_cleanup();
           return;
       }
       #
       # Write the excel file
       $excel_workbook->close();
       #
       # Close the progress window
       &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
       #
       # Tell the user where to get their excel file
       $r->print('<br />'.
                 '<a href="'.$filename.'">'.&mt('Your Excel spreadsheet').'</a>'."\n");
       $r->rflush();
       &excel_cleanup();
       return;
   }
   
   
   #
   # CSV data
   #
   # -----------
   
   #
   # Go through the complete course and collect data
   #
   
 sub getData {  sub getData {
   
Line 242  sub getData { Line 392  sub getData {
             my $stack = $iterator->getStack();              my $stack = $iterator->getStack();
                           
             for my $part (@{$parts}) {              for my $part (@{$parts}) {
  my $completionStatus = $curRes->getCompletionStatus($part);  
  my $dateStatus = $curRes->getDateStatus($part);   my $dateStatus = $curRes->getDateStatus($part);
                   my $weight = $curRes->weight($part);
                 if ($completionStatus == $curRes->EXCUSED()) {                  my $problemstatus = $curRes->problemstatus($part);
   
                   if ($curRes->solved($part) eq 'excused') {
                     next;                      next;
                 }                  }
  if ($showPoints) {   if ($showPoints) {
     my $score = 0;      my $score = 0;
     # If we're not telling status and the answer date isn't passed yet,       # If we're not telling status and the answer date isn't passed yet, 
     # it's an "attempted" point      # it's an "attempted" point
     if ((($curRes->problemstatus($part) eq 'no') ||      if ((($problemstatus eq 'no') ||
                         ($curRes->problemstatus($part) eq 'no_feedback_ever')) &&                           ($problemstatus eq 'no_feedback_ever')) &&
  ($dateStatus != $curRes->ANSWER_OPEN)) {   ($dateStatus != $curRes->ANSWER_OPEN)) {
  my $status = $curRes->simpleStatus($part);   my $status = $curRes->simpleStatus($part);
  if ($status == $curRes->ATTEMPTED) {   if ($status == $curRes->ATTEMPTED) {
     $partsAttempted += $curRes->weight($part);      $partsAttempted += $weight;
     $totalAttempted += $partsAttempted;      $totalAttempted += $partsAttempted;
  }   }
     } else {      } else {
  $score = &Apache::grades::compute_points($curRes->weight($part), $curRes->awarded($part));   $score = &Apache::grades::compute_points($weight, $curRes->awarded($part));
     }      }
     $partsRight += $score;      $partsRight += $score;
     $totalRight += $score;      $totalRight += $score;
     $partsCount += $curRes->weight($part);      $partsCount += $weight;
   
                     $curRes->{DATA}->{PROB_SCORE}  += $score;                      $curRes->{DATA}->{PROB_SCORE}  += $score;
                     $curRes->{DATA}->{PROB_WEIGHT} += $curRes->weight($part);                      $curRes->{DATA}->{PROB_WEIGHT} += $weight;
   
     if ($curRes->opendate($part) < $now) {      if ($curRes->opendate($part) < $now) {
  $totalPossible += $curRes->weight($part);   $totalPossible += $weight;
                         $curRes->{DATA}->{PROB_POSSIBLE} += $curRes->weight($part);                          $curRes->{DATA}->{PROB_POSSIBLE} += $weight;
     }      }
     $totalParts += $curRes->weight($part);      $totalParts += $weight;
  } else {   } else {
     my $status = $curRes->simpleStatus($part);      my $status = $curRes->simpleStatus($part);
     my $thisright = 0;      my $thisright = 0;
Line 291  sub getData { Line 442  sub getData {
  $totalAttempted++;   $totalAttempted++;
     }      }
           
     my $dateStatus = $curRes->getDateStatus($part);  
     $totalParts++;      $totalParts++;
     if ($curRes->opendate($part) < $now) {      if ($curRes->opendate($part) < $now) {
  $totalPossible++;   $totalPossible++;
Line 461  sub outputCategories { Line 611  sub outputCategories {
         &Apache::lonnet::put('grading_categories',\%categories,$cdom,$cnum);          &Apache::lonnet::put('grading_categories',\%categories,$cdom,$cnum);
     }      }
 # new categories loaded now  # new categories loaded now
     &output_category_table($r,$cangrade,$navmap,%categories);      &output_category_table($r,$cangrade,$navmap,1,%categories);
 #  #
     if ($cangrade) {      if ($cangrade) {
         $r->print(&Apache::loncommon::resourcebrowser_javascript().          $r->print(&Apache::loncommon::resourcebrowser_javascript().
Line 471  sub outputCategories { Line 621  sub outputCategories {
                   '<input type="submit" name="storechanges" value="'.&mt("Save changes to grading categories").'" />'.                    '<input type="submit" name="storechanges" value="'.&mt("Save changes to grading categories").'" />'.
                   '<script>function storecmd (cmd) { document.quickform.cmd.value=cmd; document.quickform.submit(); }</script>');                    '<script>function storecmd (cmd) { document.quickform.cmd.value=cmd; document.quickform.submit(); }</script>');
     }      }
 #  
 # Debug  
 #  
 #    my %data=&dumpdata($navmap);  
 #    foreach (keys(%data)) {  
 #        $r->print("\n<br />".$_.'='.$data{$_});  
 #    }  
 #   my @debugarray=('5:1','4:3','1:1','5:5','6:7');  
 #   $r->print("Array: ".join(',',@debugarray).'<br />');  
 #   $r->print("0,0,0: ".join(',',&drop(0,0,0,@debugarray)).'<br />');  
 #   $r->print("1,0,0: ".join(',',&drop(1,0,0,@debugarray)).'<br />');  
 #   $r->print("0,1,0: ".join(',',&drop(0,1,0,@debugarray)).'<br />');  
 #   $r->print("1,1,0: ".join(',',&drop(1,1,0,@debugarray)).'<br />');  
 #  
 #   $r->print("0,0,2: ".join(',',&drop(0,0,2,@debugarray)).'<br />');  
 #   $r->print("1,0,2: ".join(',',&drop(1,0,2,@debugarray)).'<br />');  
 #   $r->print("0,1,2: ".join(',',&drop(0,1,2,@debugarray)).'<br />');  
 #   $r->print("1,1,2: ".join(',',&drop(1,1,2,@debugarray)).'<br />');  
 #  
 #   $r->print("0,0,4: ".join(',',&drop(0,0,4,@debugarray)).'<br />');  
 #   $r->print("1,0,4: ".join(',',&drop(1,0,4,@debugarray)).'<br />');  
 #   $r->print("0,1,4: ".join(',',&drop(0,1,4,@debugarray)).'<br />');  
 #   $r->print("1,1,4: ".join(',',&drop(1,1,4,@debugarray)).'<br />');  
 #  
 #   $r->print("0,0,5: ".join(',',&drop(0,0,5,@debugarray)).'<br />');  
 #   $r->print("1,0,5: ".join(',',&drop(1,0,5,@debugarray)).'<br />');  
 #   $r->print("0,1,5: ".join(',',&drop(0,1,5,@debugarray)).'<br />');  
 #   $r->print("1,1,5: ".join(',',&drop(1,1,5,@debugarray)).'<br />');  
 #  
 #   $r->print("0,0,7: ".join(',',&drop(0,0,7,@debugarray)).'<br />');  
 #   $r->print("1,0,7: ".join(',',&drop(1,0,7,@debugarray)).'<br />');  
 #   $r->print("0,1,7: ".join(',',&drop(0,1,7,@debugarray)).'<br />');  
 #   $r->print("1,1,7: ".join(',',&drop(1,1,7,@debugarray)).'<br />');  
   
 }  }
   
 #  #
Line 587  sub process_category_edits { Line 703  sub process_category_edits {
 #  #
   
 sub output_category_table {  sub output_category_table {
     my ($r,$cangrade,$navmaps,%categories)=@_;      my ($r,$cangrade,$navmaps,$output,%categories)=@_;
           
     my $totalweight=0;      my $totalweight=0;
     my $totalpoints=0;      my $totalpoints=0;
   
     $r->print(&Apache::loncommon::start_data_table());      if ($output) { 
          $r->print(&Apache::loncommon::start_data_table());
 #  #
     &output_category_table_header($r,$cangrade);         &output_category_table_header($r,$cangrade);
       }
 #  #
     my @order=split(/\,/,$categories{'order'});      my @order=split(/\,/,$categories{'order'});
 #  #
     my %performance=&dumpdata($navmaps);      my %performance=&dumpdata($navmaps);
     my $maxpos=$#order;      my $maxpos=$#order;
     for (my $i=0;$i<=$maxpos;$i++) {      for (my $i=0;$i<=$maxpos;$i++) {
         my ($correct,$possible,$type,$weight)=&output_and_calc_category($r,$cangrade,$navmaps,$order[$i],$i,$maxpos,\%performance,1,%categories);          my ($correct,$possible,$type,$weight)=&output_and_calc_category($r,$cangrade,$navmaps,$order[$i],$i,$maxpos,\%performance,$output,%categories);
         unless ($possible) { next; }          unless ($possible) { next; }
         $totalpoints+=$weight*$correct/$possible;          $totalpoints+=$weight*$correct/$possible;
         $totalweight+=$weight;          $totalweight+=$weight;
Line 610  sub output_category_table { Line 728  sub output_category_table {
     my $perc=0;      my $perc=0;
     if ($totalweight) { $perc=100.*$totalpoints/$totalweight; }      if ($totalweight) { $perc=100.*$totalpoints/$totalweight; }
   
     &bottom_line_category($r,$cangrade,$perc);      if ($output) { 
 #          &bottom_line_category($r,$cangrade,$perc); 
     $r->print(&Apache::loncommon::end_data_table());          $r->print(&Apache::loncommon::end_data_table());
       }
     return $perc;      return $perc;
 }  }
   
Line 638  sub output_category_table_header { Line 757  sub output_category_table_header {
   
 sub output_and_calc_category {  sub output_and_calc_category {
     my ($r,$cangrade,$navmaps,$id,$currentpos,$maxpos,$performance,$output,%categories)=@_;      my ($r,$cangrade,$navmaps,$id,$currentpos,$maxpos,$performance,$output,%categories)=@_;
       
       if ($output) { $r->print("\n".&Apache::loncommon::start_data_table_row()); }
   
     my $iconpath = &Apache::loncommon::lonhttpdurl($r->dir_config('lonIconsURL') . "/");      if ($output && $cangrade) {
     my %lt=&Apache::lonlocal::texthash(          my $iconpath = &Apache::loncommon::lonhttpdurl($r->dir_config('lonIconsURL') . "/");
           my %lt=&Apache::lonlocal::texthash(
            'up' => 'Move Up',             'up' => 'Move Up',
            'dw' => 'Move Down');             'dw' => 'Move Down');
     if ($output) { $r->print("\n".&Apache::loncommon::start_data_table_row()); }  
   
     if ($output && $cangrade) {  
         $r->print(<<ENDMOVE);          $r->print(<<ENDMOVE);
 <td>  <td>
 <div class="LC_docs_entry_move">  <div class="LC_docs_entry_move">

Removed from v.1.96  
changed lines
  Added in v.1.104


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