Diff for /loncom/interface/lonquickgrades.pm between versions 1.32 and 1.71

version 1.32, 2004/10/07 22:12:47 version 1.71, 2011/02/20 23:57:35
Line 25 Line 25
 #  #
 # http://www.lon-capa.org/  # http://www.lon-capa.org/
 #  #
 # Created Nov. 14, 2002 by Jeremy Bowers  
   
 package Apache::lonquickgrades;  package Apache::lonquickgrades;
   
Line 34  use Apache::Constants qw(:common :http); Line 33  use Apache::Constants qw(:common :http);
 use POSIX;  use POSIX;
 use Apache::loncommon;  use Apache::loncommon;
 use Apache::lonlocal;  use Apache::lonlocal;
   use Apache::lonnet;
   use Apache::grades;
   
 sub handler {  sub handler {
     my $r = shift;      my $r = shift;
Line 46  sub real_handler { Line 47  sub real_handler {
     &Apache::loncommon::get_unprocessed_cgi($ENV{QUERY_STRING});      &Apache::loncommon::get_unprocessed_cgi($ENV{QUERY_STRING});
   
     # Handle header-only request      # Handle header-only request
       if ($env{'browser.mathml'}) {
    &Apache::loncommon::content_type($r,'text/xml');
       } else {
    &Apache::loncommon::content_type($r,'text/html');
       }
     if ($r->header_only) {      if ($r->header_only) {
         if ($ENV{'browser.mathml'}) {   $r->send_http_header;
             &Apache::loncommon::content_type($r,'text/xml');  
         } else {  
             &Apache::loncommon::content_type($r,'text/html');  
         }  
         $r->send_http_header;  
         return OK;          return OK;
     }      }
   
     # Send header, don't cache this page      # Send header, don't cache this page
     if ($ENV{'browser.mathml'}) {  
         &Apache::loncommon::content_type($r, 'text/xml');  
     } else {  
         &Apache::loncommon::content_type($r, 'text/html');  
     }  
     &Apache::loncommon::no_cache($r);      &Apache::loncommon::no_cache($r);
     $r->send_http_header;      $r->send_http_header;
   
     my $showPoints =       my $showPoints =
         $ENV{'course.'.$ENV{'request.course.id'}.'.grading'} eq 'standard';          $env{'course.'.$env{'request.course.id'}.'.grading'} eq 'standard';
     my $notshowSPRSlink =       my $notshowSPRSlink =
         $ENV{'course.'.$ENV{'request.course.id'}.'.grading'} eq 'external';          (($env{'course.'.$env{'request.course.id'}.'.grading'} eq 'external')
         || ($env{'course.'.$env{'request.course.id'}.'.grading'} eq 'externalnototals'));
       my $notshowTotals=
           $env{'course.'.$env{'request.course.id'}.'.grading'} eq 'externalnototals';
       my $showCategories=
           $env{'course.'.$env{'request.course.id'}.'.grading'} eq 'categories';
   
   
       my $title = "Grading and Statistics";#$showPoints ? "Points Display" : "Completed Problems Display";
       my $brcrum = [{href=>"/adm/quickgrades",text => "Points Display"}];
       $r->print(&Apache::loncommon::start_page($title,undef,
                                               {'bread_crumbs' => $brcrum})
                );
   
     # Create the nav map      &startGradeScreen($r,'quick');
     my $navmap = Apache::lonnavmaps::navmap->new();  
       $r->rflush();
   
   #    my $uname='korte';
   #    my $udom='gerd';
   
       my $uname;
       my $udom;
   
     if (!defined($navmap)) {      my ($navmap,$totalParts,$totalPossible,$totalRight,$totalAttempted,$topLevelParts,$topLevelRight,$topLevelAttempted)=
         my $requrl = $r->uri;         &getData($showPoints,$uname,$udom);
         $ENV{'user.error.msg'} = "$requrl:bre:0:0:Navamp initialization failed.";  
         return HTTP_NOT_ACCEPTABLE;      if ($showCategories) {
          &outputCategories($r,$showPoints,$notshowTotals,
                    $navmap,$totalParts,$totalPossible,$totalRight,$totalAttempted,$topLevelParts,$topLevelRight,$topLevelAttempted);
       } else {
          &outputTable($r,$showPoints,$notshowTotals,
                    $navmap,$totalParts,$totalPossible,$totalRight,$totalAttempted,$topLevelParts,$topLevelRight,$topLevelAttempted);
     }      }
       &endGradeScreen($r);
       return OK;
   
     # Keep this hash in sync with %statusIconMap in lonnavmaps; they  }
     # should match color/icon  
     my $res = $navmap->firstResource(); # temp resource to access constants  sub startGradeScreen {
        my ($r,$mode)=@_;
     # Header  
     my $title = $showPoints ? "Points Display" : "Completed Problems Display";      my $showPoints =
     $r->print(&Apache::loncommon::bodytag($title, '', ''));          $env{'course.'.$env{'request.course.id'}.'.grading'} eq 'standard';
       my $notshowSPRSlink =
     if (!$showPoints && !$notshowSPRSlink ) {          (($env{'course.'.$env{'request.course.id'}.'.grading'} eq 'external')
         $r->print(<<HEADER);         || ($env{'course.'.$env{'request.course.id'}.'.grading'} eq 'externalnototals')
 <p>This screen shows how many problems (or problem parts) you have completed, and        || ($env{'course.'.$env{'request.course.id'}.'.grading'} eq 'categories'));
 how many you have not yet done. You can also look at <a href="/adm/studentcalc">a detailed      my $notshowTotals=
 score sheet</a>.</p>          $env{'course.'.$env{'request.course.id'}.'.grading'} eq 'externalnototals';
 HEADER      my $showCategories=
           $env{'course.'.$env{'request.course.id'}.'.grading'} eq 'categories';
   
       my $allowed_to_view =  &Apache::lonnet::allowed('vgr',$env{'request.course.id'});
       my $allowed_to_edit =  &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
   
       if ($allowed_to_view) {
          my @notes;
          push(@notes,&mt('Students do not see total points.')) if ($notshowTotals);
          push(@notes,&mt('Students do not see link to spreadsheet.')) if ($notshowSPRSlink);
          push(@notes,&mt('Students will see points based on problem weights.')) if ($showPoints);
          push(@notes,&mt('Students will see points based on categories.')) if ($showCategories);
          push(@notes, &Apache::lonhtmlcommon::coursepreflink(&mt('Grade display settings'),'grading'));
          $r->print(&Apache::loncommon::head_subbox(join('&nbsp;&nbsp;',@notes)));
     }      }
   
     $r->print("This may take a few moments to display.");  
   
     $r->rflush();      $r->print("\n".'<ul class="LC_TabContentBigger" id="main">');
       $r->print("\n".'<li'.($mode eq 'quick'?' class="active"':'').'><a href="/adm/quickgrades"><b>&nbsp;&nbsp;&nbsp;&nbsp;'.
                                             ($showPoints?&mt('Individual Points Overview'):($showCategories?&mt('Grades Overview'):&mt('Completion Overview'))).
                                             '&nbsp;&nbsp;&nbsp;&nbsp;</b></a></li>');
   
       if (!($showPoints || $notshowSPRSlink) || ($allowed_to_view)) {
          $r->print("\n".'<li'.($mode eq 'spreadsheet'?' class="active"':'').'><a href="/adm/'.($allowed_to_view?'classcalc':'studentcalc').'"><b>'.
                                                                    &mt('Spreadsheet (Detailed)').'</b></a></li>');
       }
       if ($allowed_to_view) {
          $r->print("\n".'<li'.($mode eq 'statistics'?' class="active"':'').'><a href="/adm/statistics"><b>'.
                                                                    &mt('Statistics and Reports').'</b></a></li>');
   
     # End navmap using boilerplate         $r->print("\n".'<li'.($mode eq 'chart'?' class="active"':'').'><a href="/adm/statistics?reportSelected=student_assessment"><b>'.
                                                                    &mt('Assessment Overview Chart').'</b></a></li>');
   
       }
       if ($allowed_to_edit) {
          $r->print("\n".'<li'.($mode eq 'grading'?' class="active"':'').'><a href="/adm/grades"><b>&nbsp;&nbsp;&nbsp;&nbsp;'.
                                                                    &mt('Content Grading').'&nbsp;&nbsp;&nbsp;&nbsp;</b></a></li>');
          if ($env{'form.symb'}) {
             $r->print("\n".'<li'.($mode eq 'probgrading'?' class="active"':'').'><a href="/adm/grades?symb='.
                                                 &Apache::lonhtmlcommon::entity_encode($env{'form.symb'}).
                                                 '&command=gradingmenu"><b>&nbsp;&nbsp;&nbsp;&nbsp;'.
                                                 &mt('Problem Grading').'&nbsp;&nbsp;&nbsp;&nbsp;</b></a></li>');
   
          }
       }
       $r->print("\n".'</ul>'."\n");
       $r->print('<div class="LC_Box" style="clear:both;margin:0;"><div id="maincoursedoc" style="margin:0 0;padding:0 0;"><div class="LC_ContentBox" id="mainCourseDocuments" style="display: block;">');
   }
   
   sub endGradeScreen {
      my ($r)=@_;
      $r->print('</div></div></div>');
   }
   
   
   sub getData {
   
       my ($showPoints,$uname,$udom)=@_;
   
       # Create the nav map
       my $navmap = Apache::lonnavmaps::navmap->new($uname,$udom);
   
       my $res = $navmap->firstResource(); # temp resource to access constants
   
     my $iterator = $navmap->getIterator(undef, undef, undef, 1);      my $iterator = $navmap->getIterator(undef, undef, undef, 1);
     my $depth = 1;      my $depth = 1;
Line 148  HEADER Line 225  HEADER
     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 ((($curRes->problemstatus($part) eq 'no') ||
                           ($curRes->problemstatus($part) 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) {
Line 156  HEADER Line 234  HEADER
     $totalAttempted += $partsAttempted;      $totalAttempted += $partsAttempted;
  }   }
     } else {      } else {
  $score = $curRes->weight($part) * $curRes->awarded($part);   $score = &Apache::grades::compute_points($curRes->weight($part), $curRes->awarded($part));
     }      }
     $partsRight += $score;      $partsRight += $score;
     $totalRight += $score;      $totalRight += $score;
Line 170  HEADER Line 248  HEADER
     my $status = $curRes->simpleStatus($part);      my $status = $curRes->simpleStatus($part);
     my $thisright = 0;      my $thisright = 0;
     $partsCount++;      $partsCount++;
     if ($status == $curRes->CORRECT ||       if ($status == $curRes->CORRECT ||
  $status == $curRes->INCORRECT ) {   $status == $curRes->PARTIALLY_CORRECT ) {
  $partsRight++;   $partsRight++;
  $totalRight++;   $totalRight++;
  $thisright = 1;   $thisright = 1;
Line 213  HEADER Line 291  HEADER
         }          }
         $curRes = $iterator->next();          $curRes = $iterator->next();
     }      }
       return ($navmap,$totalParts,$totalPossible,$totalRight,$totalAttempted,$topLevelParts,$topLevelRight,$topLevelAttempted);
   }
   
     $iterator = $navmap->getIterator(undef, undef, undef, 1);  #
     $depth = 1;  # Outputting everything.
     $iterator->next(); # ignore first BEGIN_MAP  #
     $curRes = $iterator->next();  
   sub outputTable {
   
       my ($r,$showPoints,$notshowTotals,
              $navmap,$totalParts,$totalPossible,$totalRight,$totalAttempted,$topLevelParts,$topLevelRight,$topLevelAttempted)=@_;
   
     my @start = (255, 255, 192);      my @start = (255, 255, 192);
     my @end   = (0, 192, 0);      my @end   = (0, 192, 0);
Line 225  HEADER Line 309  HEADER
     my $indentString = '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';      my $indentString = '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
   
     # Second pass: Print the maps.      # Second pass: Print the maps.
     $r->print('<table cellspacing="3" border="2"><tr><td align="center"><b>' .      $r->print(&Apache::loncommon::start_data_table()
       &mt('Folder') . '</b></td>');               .&Apache::loncommon::start_data_table_header_row()
     $title = &mt($showPoints ? "Points Scored" : "Done");               .'<th>'.&mt('Folder').'</th>');
       my $title = &mt($showPoints ? "Points Scored" : "Done");
     if ($totalAttempted) {      if ($totalAttempted) {
  $title .= " / " . &mt("Attempted");          $title .= " / " . &mt("Attempted");
     }      }
     $r->print("<td align='center'>$title / "      $r->print("<th>$title".($notshowTotals?'':" / ".&mt('Total')).'</th>'
       . &mt('Total') . "</td><tr>\n\n");               .&Apache::loncommon::end_data_table_header_row());
   #
   # Output of folder scores
   #
   
       my $iterator = $navmap->getIterator(undef, undef, undef, 1);
       my $depth = 1;
       $iterator->next(); # ignore first BEGIN_MAP
       my $curRes = $iterator->next();
   
     while ($depth > 0) {      while ($depth > 0) {
         if ($curRes == $iterator->BEGIN_MAP()) {$depth++;}          if ($curRes == $iterator->BEGIN_MAP()) {$depth++;}
         if ($curRes == $iterator->END_MAP()) { $depth--; }          if ($curRes == $iterator->END_MAP()) { $depth--; }
Line 247  HEADER Line 341  HEADER
             if ($total > 0) {              if ($total > 0) {
                 my $ratio;                  my $ratio;
                 $ratio = $correct / $total;                  $ratio = $correct / $total;
                 my $color = mixColors(\@start, \@end, $ratio);                  my $color = &mixColors(\@start, \@end, $ratio);
                 $r->print("<tr><td bgcolor='$color'>");                  $r->print(&Apache::loncommon::start_data_table_row()
                            .'<td style="background-color:'.$color.';">');
                                   
  my $thisIndent = '';   my $thisIndent = '';
                 for (my $i = 1; $i < $depth; $i++) { $thisIndent .= $indentString; }                  for (my $i = 1; $i < $depth; $i++) { $thisIndent .= $indentString; }
                                   
                 $r->print("$thisIndent$title</td>");                  $r->print("$thisIndent$title</td>");
  if ($totalAttempted) {   if ($totalAttempted) {
     $r->print("<td valign='top'>$thisIndent<nobr>$correct / $attempted / $total</nobr></td></tr>\n");      $r->print('<td valign="top">'
                                .$thisIndent
                                .'<span class="LC_nobreak">'
                                .$correct.' / '.$attempted.($notshowTotals?'':' / '.$total)
                                .'</span></td>'
                                .&Apache::loncommon::end_data_table_row()
                       );
  } else {   } else {
     $r->print("<td valign='top'>$thisIndent<nobr>$correct / $total</nobr></td></tr>\n");      $r->print('<td valign="top">'
                                .$thisIndent
                                .'<span class="LC_nobreak">'
                                .$correct.($notshowTotals?'':' / '.$total)
                                .'</span></td>'
                                .&Apache::loncommon::end_data_table_row());
  }   }
             }              }
         }          }
Line 268  HEADER Line 374  HEADER
     # If there were any problems at the top level, print an extra "catchall"      # If there were any problems at the top level, print an extra "catchall"
     if ($topLevelParts > 0) {      if ($topLevelParts > 0) {
         my $ratio = $topLevelRight / $topLevelParts;          my $ratio = $topLevelRight / $topLevelParts;
         my $color = mixColors(\@start, \@end, $ratio);          my $color = &mixColors(\@start, \@end, $ratio);
         $r->print("<tr><td bgcolor='$color'>");          $r->print(&Apache::loncommon::start_data_table_row()
                    .'<td style="background-color:'.$color.';">');
         $r->print(&mt("Problems Not Contained In A Folder")."</td><td>");          $r->print(&mt("Problems Not Contained In A Folder")."</td><td>");
         $r->print("$topLevelRight / $topLevelParts</td></tr>");          $r->print("$topLevelRight / $topLevelParts</td>"
                    .&Apache::loncommon::end_data_table_row());
     }      }
   
     my $maxHelpLink = Apache::loncommon::help_open_topic("Quick_Grades_Possibly_Correct");  #
   # show totals (if applicable), close table
   #
       if ($showPoints) {
           my $maxHelpLink = &Apache::loncommon::help_open_topic("Quick_Grades_Possibly_Correct");
   
     $title = $showPoints ? "Points" : "Parts Done";          $title = $showPoints ? "Points" : "Parts Done";
           my $totaltitle = $showPoints ? &mt("Awarded Total Points") : &mt("Total Parts Done");
           $r->print(&Apache::loncommon::start_data_table_row()
                    .'<td colspan="2" align="right">'.$totaltitle.': <b>'.$totalRight.'</b><br />');
           $r->print(&mt('Max Possible To Date')." $maxHelpLink: <b>$totalPossible</b><br />");
           $title = $showPoints ? "Points" : "Parts";
           $r->print(&mt("Total $title In Course").': <b>'.$totalParts.'</b></td>'
                    .&Apache::loncommon::end_data_table_row());
       }
   
     $r->print("<tr><td colspan='2' align='right'>Total $title: <b>$totalRight</b><br>");      $r->print(&Apache::loncommon::end_data_table()
     $r->print(&mt("Max Possible To Date")." $maxHelpLink: <b>$totalPossible</b><br>");               .&Apache::loncommon::end_page());
     $title = $showPoints ? "Points" : "Parts";  
     $r->print(&mt("Total $title In Course").": <b>$totalParts</b></td></tr>\n\n");  
   
   }
   
     $r->print("</table></body></html>");  #
   # === Outputting category-based grades.
   #
   # $category{'order'}: output order of categories by id
   # $category{'all'}: complete list of all categories 
   # $category{$id.'_name'}: display-name of category
   #
   
     return OK;  sub outputCategories {
   
       my ($r,$showPoints,$notshowTotals,
              $navmap,$totalParts,$totalPossible,$totalRight,$totalAttempted,$topLevelParts,$topLevelRight,$topLevelAttempted)=@_;
   # Take care of storing and retrieving categories
   
       my $cangrade=&Apache::lonnet::allowed('mgr');
   
       my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
       my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
       my %categories=();
   # Loading old categories
       %categories=&Apache::lonnet::dump('grading_categories',$cdom,$cnum);
   # Storing
       if (($cangrade) && (($env{'form.storechanges'}) || ($env{'form.storemove'} ne ''))) {
   # Process the changes
           %categories=&process_category_edits($r,$cangrade,%categories);
   # Actually store
           &Apache::lonnet::logthis("Storing ".$categories{'order'});
           &Apache::lonnet::put('grading_categories',\%categories,$cdom,$cnum);
       }
   # new categories loaded now
   # Form only generated if user can change the grading categories
       if ($cangrade) {
           $r->print('<form method="post">');
       }
   #
       &output_category_table($r,$cangrade,$navmap,%categories);
   #
       if ($cangrade) {
           $r->print('<input type="hidden" name="storemove" value="" />'.
                     '<input type="submit" name="storechanges" value="'.&mt("Save changes to grading categories").'" /></form>');
       }
   }
   
   #
   # Process editing commands, update category hash
   #
   
   sub process_category_edits {
       my ($r,$cangrade,%categories)=@_;
       unless ($cangrade) { return %categories; }
       my $cmd=$env{'form.cmd'};
       if ($cmd eq 'createnewcat') {
           %categories=&make_new_category($r,$cangrade,undef,%categories);
       } elsif ($cmd=~/^delcat\_(.+)$/) {
           %categories=&del_category($1,$cangrade,%categories);
       } else {
   # Simply store the rest of the stuff
           foreach my $id (split(/\,/,$categories{'order'})) {
               %categories=&set_category_name($cangrade,$id,$env{'form.name_'.$id},%categories);
               %categories=&set_category_total($cangrade,$id,$env{'form.totaltype_'.$id},$env{'form.total_'.$id},%categories);
               %categories=&set_category_weight($cangrade,$id,$env{'form.weight_'.$id},%categories);
   # More changes here
           }
       }
       return %categories;
   }
   
   #
   # Output the table
   #
   
   sub output_category_table {
       my ($r,$cangrade,$navmaps,%categories)=@_;
       my $sum=0;
       my $total=0;
       $r->print(&Apache::loncommon::start_data_table());
   #
       &output_category_table_header($r,$cangrade);
   #
       my @order=split(/\,/,$categories{'order'});
   #
       my $maxpos=$#order;
       for (my $i=0;$i<=$maxpos;$i++) {
           my ($value,$weight)=&output_and_calc_category($r,$cangrade,$navmaps,$order[$i],$i,$maxpos,%categories);
           $sum+=$value*$weight;
           $total+=$weight;
       }
   #
       &bottom_line_category($r,$cangrade,$sum,$total);
   #
       $r->print(&Apache::loncommon::end_data_table());
       return $sum;
   }
   
   sub output_category_table_header {
       my ($r,$cangrade)=@_;
       $r->print(&Apache::loncommon::start_data_table_header_row());
       if ($cangrade) {
           $r->print('<th colspan="2">'.&mt("Move").'</th><th>'.&mt('Action').'</th>');
       }
       $r->print('<th>'.&mt('Category').'</th>'.
                 '<th>'.&mt('Contents').'</th>'.
                 '<th>'.&mt('Calculation').'</th>'.
                 '<th>'.&mt('Total Points').'</th>'.
                 '<th>'.&mt('Relative Weight').'</th>');
       $r->print(&Apache::loncommon::end_data_table_header_row());
   }
   
   
   #
   # Output one category to table
   #
   
   sub output_and_calc_category {
       my ($r,$cangrade,$navmaps,$id,$currentpos,$maxpos,%categories)=@_;
       my $value=0;
       my $weight=0;
       my $iconpath = &Apache::loncommon::lonhttpdurl($r->dir_config('lonIconsURL') . "/");
       my %lt=&Apache::lonlocal::texthash(
              'up' => 'Move Up',
              'dw' => 'Move Down');
       $r->print("\n".&Apache::loncommon::start_data_table_row());
   
       if ($cangrade) {
           $r->print(<<ENDMOVE);
   <td>
   <div class="LC_docs_entry_move">
     <a href='/adm/quickgrades?cmd=up_$id&storechanges=1'>
       <img src="${iconpath}move_up.gif" alt='$lt{'up'}' class="LC_icon" />
     </a>
   </div>
   <div class="LC_docs_entry_move">
     <a href='/adm/quickgrades?cmd=down_$id&storechanges=1'>
       <img src="${iconpath}move_down.gif" alt='$lt{'dw'}' class="LC_icon" />
     </a>
   </div>
   </td>
   ENDMOVE
           $r->print("\n<td>\n<select name='newpos_$id' onchange='this.form.storemove.value=\"$id\";this.form.submit()'>");
           for (my $i=0;$i<=$maxpos;$i++) {
               if ($i==$currentpos) {
                   $r->print('<option value="" selected="selected">('.$i.')</option>');
               } else {
                   $r->print('<option value="'.$i.'">'.$i.'</option>');
               }
           }
           $r->print("\n</select>\n</td>\n");
           $r->print('<td><a href="/adm/quickgrades?cmd=delcat_'.$id.'&storechanges=1">'.&mt('Delete').'</a></td>');
           $r->print('<td><input type="text" name="name_'.$id.
                     '" value="'.&Apache::lonhtmlcommon::entity_encode($categories{$id.'_name'}).'" /></td>');
       } else {
           $r->print('<td>'.$categories{$id.'_name'}.'</td>');
       }
   # Content
   # FIXME: just placeholders
       if ($cangrade) {
          $r->print("<td>Content Edit</td>");
       } else {
          $r->print("<td>Content</td>");
       }
   # Calculation
   # FIXME: just placeholders
       if ($cangrade) {
          $r->print("<td>Calculation Edit</td>");
       } else {
          $r->print("<td>Calculation</td>");
       }
   # Total
       if ($cangrade) {
          $r->print('<td>'.
                     '<select name="totaltype_'.$id.'">'.
                     '<option value="default"'.($categories{$id.'_totaltype'} eq 'default'?' selected="selected"':'').'>'.&mt('default').'</option>'.
                     '<option value="typein"'.($categories{$id.'_totaltype'} eq 'typein'?' selected="selected"':'').'>'.&mt('Type-in value').'</option>'.
                     '</select>'.
                     '<input type="text" size="4" name="total_'.$id.
                     '" value="'.&Apache::lonhtmlcommon::entity_encode($categories{$id.'_total'}).'" /></td>');
       } else {
           $r->print('<td>'.($categories{$id.'_totaltype'} eq 'default'?&mt('default'):$categories{$id.'_total'}).'</td>');
       }
   # Weight
       if ($cangrade) {
          $r->print('<td>'.
                     '<input type="text" size="4" name="weight_'.$id.
                     '" value="'.&Apache::lonhtmlcommon::entity_encode($categories{$id.'_weight'}).'" /></td>');
       } else {
           $r->print('<td>'.$categories{$id.'_weight'}.'</td>');
       }
   
       return ($value,$weight);
   }
   
   #
   # Bottom line with grades
   #
   
   sub bottom_line_category {
       my ($r,$cangrade,$sum,$total)=@_;
       $r->print(&Apache::loncommon::start_data_table_row());
       if ($cangrade) {
           $r->print('<td colspan="3"><a href="/adm/quickgrades?cmd=createnewcat&storechanges=1">'.&mt('Create New Category').'</a></td>');
       }
       $r->print('<td colspan="5">'.&mt('Current:').$sum.'<br />'.&mt('Total:').$total.'<br /></td>');
   }
   
   #
   # Make one new category
   #
   
   sub make_new_category {
       my ($r,$cangrade,$ordernum,%categories)=@_;
       unless ($cangrade) { return %categories; }
   # Generate new ID
       my $id=time.'_'.$$.'_'.rand(10000);
   # Add new ID to list of all IDs ever created in this course
       $categories{'all'}.=','.$id;
       $categories{'all'}=~s/^\,//;
   # Add new ID to ordered list of displayed and evaluated categories
       $categories{'order'}.=','.$id;
       $categories{'order'}=~s/^\,//;
   # Move it into desired space
       if (defined($ordernum)) {
           %categories=&move_category($id,$cangrade,$ordernum,%categories);
       }
       $categories{$id.'_weight'}=0;
       $categories{$id.'_totaltype'}='default';
       return %categories;
 }  }
   
   #
   # Delete category
   #
   
   sub del_category {
      my ($id,$cangrade,%categories)=@_; 
      my @neworder=();
      foreach my $currentid (split(/\,/,$categories{'order'})) {
         unless ($currentid eq $id) {
            push(@neworder,$currentid);
         }
      }
      $categories{'order'}=join(',',@neworder);
      return %categories;
   }
   
   #
   # Move a category to a desired position n the display order
   #
   
   sub move_category {
       my ($id,$cangrade,$ordernum,%categories)=@_;
       unless ($cangrade) { return %categories; }
       my @order=split(/\,/,$categories{'order'});
   # Where is the index currently?
       my $currentpos=&current_pos_category($id,%categories);
       if (defined($currentpos)) {
           if ($currentpos<$ordernum) {
   # This is moving to a higher index
   # ....X1234....
   # ....1234X....
               for (my $i=$currentpos;$i<$ordernum;$i++) {
                   $order[$i]=$order[$i+1];
               }
               $order[$ordernum]=$id;
           }
           if ($currentpos>$ordernum) {
   # This is moving to a lower index
   # ....1234X....
   # ....X1234....
               for (my $i=$currentpos;$i>$ordernum;$i--) {
                   $order[$i]=$order[$i-1];
               }
               $order[$ordernum]=$id;
           }
       }
       $categories{'order'}=join(',',@order);
       return %categories;
   }
   
   #
   #  Find current postion of a category in the order
   #
   
   sub current_pos_category {
       my ($id,%categories)=@_;
       my @order=split(/\,/,$categories{'order'});
       for (my $i=0;$i<=$#order;$i++) {
           if ($order[$i] eq $id) { return $i; }
       }
   # not found
       return undef;
   }
   
   #
   # Set name of a category
   #
   sub set_category_name {
       my ($cangrade,$id,$name,%categories)=@_;
       unless ($cangrade) { return %categories; }
       $categories{$id.'_name'}=$name;
       return %categories;
   }
   
   #
   # Set total of a category
   #
   sub set_category_total {
       my ($cangrade,$id,$totaltype,$total,%categories)=@_;
       unless ($cangrade) { return %categories; }
       if (($categories{$id.'_total'} eq '') && ($total=~/\d/)) {
           $totaltype='typein';
       }
       $categories{$id.'_totaltype'}=$totaltype;
       if ($totaltype eq 'default') {
           $categories{$id.'_total'}='';
       } else {
           $total=~s/\D//gs;
           unless ($total) { $total=0; }
           $categories{$id.'_total'}=$total;
       }
       return %categories;
   }
   
   sub set_category_weight {
       my ($cangrade,$id,$weight,%categories)=@_;
       unless ($cangrade) { return %categories; }
       $weight=~s/\D//gs;
       unless ($weight) { $weight=0; }
       $categories{$id.'_weight'}=$weight;
       return %categories;
   }
   
   #
   # === end category-related
   #
   #
 # Pass this two refs to arrays for the start and end color, and a number  # Pass this two refs to arrays for the start and end color, and a number
 # from 0 to 1 for how much of the latter you want to mix in. It will  # from 0 to 1 for how much of the latter you want to mix in. It will
 # return a string ready to show ("#FFC309");  # return a string ready to show ("#FFC309");
   
 sub mixColors {  sub mixColors {
     my $start = shift;      my $start = shift;
     my $end = shift;      my $end = shift;

Removed from v.1.32  
changed lines
  Added in v.1.71


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.