File:  [LON-CAPA] / loncom / interface / statistics / loncorrectproblemplot.pm
Revision 1.9: download - view: text, annotated - select for diffs
Sun Mar 7 20:53:41 2004 UTC (20 years, 4 months ago) by matthew
Branches: MAIN
CVS tags: HEAD
loncoursedata.pm: &get_student_scores modified to limit by time.
loncorrectproblemplot.pm: Added time limits, corrected "bin"ing bug which
    caused the last data set to be missed, plot title is now the sequence
    being analyzed or "Multiple Sequences", added "N", the number of students,
    to the title.  Added the maximum possible number of correct problems to
    the x-axis label.

    1: # The LearningOnline Network with CAPA
    2: #
    3: # $Id: loncorrectproblemplot.pm,v 1.9 2004/03/07 20:53:41 matthew Exp $
    4: #
    5: # Copyright Michigan State University Board of Trustees
    6: #
    7: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
    8: #
    9: # LON-CAPA is free software; you can redistribute it and/or modify
   10: # it under the terms of the GNU General Public License as published by
   11: # the Free Software Foundation; either version 2 of the License, or
   12: # (at your option) any later version.
   13: #
   14: # LON-CAPA is distributed in the hope that it will be useful,
   15: # but WITHOUT ANY WARRANTY; without even the implied warranty of
   16: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17: # GNU General Public License for more details.
   18: #
   19: # You should have received a copy of the GNU General Public License
   20: # along with LON-CAPA; if not, write to the Free Software
   21: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   22: #
   23: # /home/httpd/html/adm/gpl.txt
   24: #
   25: # http://www.lon-capa.org/
   26: #
   27: 
   28: package Apache::loncorrectproblemplot;
   29: 
   30: use strict;
   31: use Apache::lonnet();
   32: use Apache::loncommon();
   33: use Apache::lonhtmlcommon();
   34: use Apache::loncoursedata();
   35: use Apache::lonstatistics;
   36: use Apache::lonstathelpers;
   37: use Apache::lonlocal;
   38: 
   39: my @SubmitButtons = (
   40:                      { name => 'CreatePlot',
   41:                        text => 'Create Plot' },
   42:                      { name => 'ClearCache',
   43:                        text => 'Clear Caches' },
   44:                      { name => 'updatecaches',
   45:                        text => 'Update Student Data' },
   46:                      );
   47: 
   48: #########################################################
   49: #########################################################
   50: 
   51: =pod
   52: 
   53: =item &BuildCorrectProblemsPage
   54: 
   55: Entry point from lonstatistics to the correct problems plot page.
   56: 
   57: =cut
   58: 
   59: #########################################################
   60: #########################################################
   61: 
   62: sub BuildCorrectProblemsPage {
   63:     my ($r,$c)=@_;
   64:     #
   65:     my %Saveable_Parameters = ('Status' => 'scalar',
   66:                                'Section' => 'array');
   67:     &Apache::loncommon::store_course_settings('correct_problems_plot',
   68:                                               \%Saveable_Parameters);
   69:     &Apache::loncommon::restore_course_settings('correct_problems_plot',
   70:                                                 \%Saveable_Parameters);
   71:     #
   72:     &Apache::lonstatistics::PrepareClasslist();    
   73:     #
   74:     $r->print(&CreateInterface());
   75:     #
   76:     my @Students = @Apache::lonstatistics::Students;
   77:     #
   78:     if (@Students < 1) {
   79:         $r->print('<h2>'.
   80:                   &mt('There are no students in the sections selected').
   81:                   '</h2>');
   82:     }
   83:     #
   84:     &Apache::loncoursedata::clear_internal_caches();
   85:     if (exists($ENV{'form.ClearCache'}) || 
   86:         exists($ENV{'form.updatecaches'}) ||
   87:         (exists($ENV{'form.firstanalysis'}) &&
   88:          $ENV{'form.firstanalysis'} ne 'no')) {
   89:         &Apache::lonstatistics::Gather_Full_Student_Data($r);
   90:     }
   91:     if (! exists($ENV{'form.firstanalysis'})) {
   92:         $r->print('<input type="hidden" name="firstanalysis" value="yes" />');
   93:     } else {
   94:         $r->print('<input type="hidden" name="firstanalysis" value="no" />');
   95:     }
   96:     foreach my $button (@SubmitButtons) {
   97:         $r->print('<input type="submit" name="'.$button->{'name'}.'" '.
   98:                   'value="'.&mt($button->{'text'}).'" />');
   99:         $r->print('&nbsp;'x5);
  100:     }
  101:     $r->rflush();
  102:     #
  103:     # Determine which problem symbs we are to sum over
  104:     if (exists($ENV{'form.CreatePlot'})) {
  105:         my @ProblemSymbs;
  106:         my $total_parts = 0;
  107:         my $title = '';
  108:         if ($Apache::lonstatistics::SelectedMaps[0] ne 'all') {
  109:             foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()){
  110:                 if ($title eq '') {
  111:                     $title = $seq->{'title'};
  112:                 } else {
  113:                     $title = 'Multiple Sequences';
  114:                 }
  115:                 foreach my $res (@{$seq->{'contents'}}) {
  116:                     next if ($res->{'type'} ne 'assessment');
  117:                     foreach my $part (@{$res->{'parts'}}) {
  118:                         $total_parts++;
  119:                         push(@ProblemSymbs,{symb=>$res->{'symb'},
  120:                                             part=>$part});
  121:                     }
  122:                 }
  123:             }
  124:         }
  125:         my ($starttime,$endtime) = &Apache::lonstathelpers::get_time_limits();
  126:         my $score_data = &Apache::loncoursedata::get_student_scores
  127:             (\@Apache::lonstatistics::SelectedSections,
  128:              \@ProblemSymbs,
  129:              $Apache::lonstatistics::enrollment_status,undef,
  130:              $starttime,$endtime);
  131:         $r->print(&AnalyzeScoreData($score_data,$title,$total_parts));
  132:     }
  133:     return;
  134: }
  135: 
  136: #########################################################
  137: #########################################################
  138: 
  139: =pod
  140: 
  141: =item & AnalyzeScoreData($score_data)
  142: 
  143: Analyze the result of &Apache::loncoursedata::get_student_scores() and
  144: return html with a plot of the data and a table of the values and bins.
  145: 
  146: =cut
  147: 
  148: #########################################################
  149: #########################################################
  150: sub AnalyzeScoreData {
  151:     my ($score_data,$title,$total_parts) = @_;
  152:     #
  153:     # Basic check first
  154:     if (@$score_data < 1) {
  155:         return '<h2>There is no data to plot</h2>';
  156:     }
  157:     #
  158:     # Determine which bins to use
  159:     my $lowest  = $score_data->[0]->[0];
  160:     $lowest = 0;
  161:     my $highest = $score_data->[-1]->[0];
  162:     &Apache::lonnet::logthis('highest = '.$highest);
  163:     my $binsize = 1;
  164:     if ($highest > 50) { $binsize = 2; }
  165:     if ($highest > 100) { $binsize = 5; }
  166:     if ($highest > 200) { $binsize = 10; }
  167:     if ($highest > 500) { $binsize = 20; }
  168:     if ($highest > 1000) { $binsize = 50; }
  169:     if ($highest > 2000) { $binsize = 100; }
  170:     #
  171:     # Get the data into the bins (destroying $score_data in the process)
  172:     my @Bins = &bin_data($score_data,$binsize,$lowest,$highest);
  173:     my @Xdata; my @Ydata; my $max;
  174:     my $Str = '<table border="1">'."\n".'<tr><th>Range</th><th>Count</th></tr>'."\n";
  175:     my $sum = 0;
  176:     while (my $bin = shift(@Bins)) {
  177:         push (@Xdata,$bin->{'start'});
  178:         push (@Ydata,$bin->{'count'});
  179:         $sum += $bin->{'count'};
  180:         if ($bin->{'count'} > $max) {
  181:             $max = $bin->{'count'};
  182:         }
  183:         $Str.= '<tr><td>'.$bin->{'start'}.' - '.$bin->{'end'}.'</td>'.
  184:             '<td>'.$bin->{'count'}.'</td></tr>'."\n";
  185:     }
  186:     # scale max to an integer.
  187:     $max = 5*(int($max/5)+1);
  188:     $Str .= "</table><br />\n";
  189:     $title = &HTML::Entities::decode($title);
  190:     $Str = "<br />\n".&Apache::loncommon::DrawBarGraph($title.' N = '.$sum,
  191:                                  'Num Correct Problems (max:'.$total_parts.')',
  192:                                                        'Number of students',
  193:                                                        $max,
  194:                                                        undef, # colors
  195:                                                        \@Xdata,
  196:                                                        \@Ydata).
  197:                                                            "\n<br />\n".$Str;
  198:     return $Str;                                               
  199: }
  200: 
  201: 
  202: #########################################################
  203: #########################################################
  204: 
  205: =pod
  206: 
  207: =item &bin_data($data,$binsize,$startbin,$endbin)
  208: 
  209: Note: This routine destroys the array of data passed to it.
  210: 
  211: Inputs: $data: array reference - the contents of @$data must
  212:         be arrays with x and y data.  $data = [ [x1,y1],[x2,y2],...];
  213:         $binsize: Width of bins to put data in
  214:         $startbin: the starting bin.
  215:         $endbin: the ending bin.
  216: Returns: Array of Bins.  Each bin is a hash reference with the following
  217:          keys: 'start', 'count', and 'end'.
  218: 
  219: =cut
  220: 
  221: #########################################################
  222: #########################################################
  223: sub bin_data {
  224:     my ($data,$binsize,$startbin,$endbin)=@_;
  225:     return () if (! defined($data) || ref($data) ne 'ARRAY');
  226:     #
  227:     # Determine bin geometry
  228:     my $binstart = $startbin;
  229:     my $binend = $startbin+$binsize;
  230:     # put the data into bins
  231:     my @Bins;
  232:     my $count=0;
  233:     my $idx=0;
  234:     while ($idx < scalar(@$data) && ($endbin-$binend + $binsize)>0) {
  235:         my $dataset = $data->[$idx++];
  236:         my ($x,$y) = @{$dataset};
  237:         while ($x > ($binend-.001)) {
  238:             # store the old data
  239:             push (@Bins,{ start => $binstart,
  240:                           count => $count,
  241:                           end   => $binend });
  242:             # start counting again
  243:             $binstart += $binsize;
  244:             $binend += $binsize;
  245:             $count = 0;
  246:         }
  247:         $count+=$y;
  248:     }
  249:     if ($count > 0) {
  250:         push (@Bins,{ start => $binstart,
  251:                       count => $count,
  252:                       end   => $binend });
  253:     }
  254:     return @Bins;
  255: }
  256: 
  257: #########################################################
  258: #########################################################
  259: 
  260: =pod
  261: 
  262: =item &CreateInterface
  263: 
  264: Inputs: none.
  265: 
  266: Returns: HTML for the correct problems plot interface.
  267: 
  268: =cut
  269: 
  270: #########################################################
  271: #########################################################
  272: sub CreateInterface {
  273:     ##
  274:     ## Environment variable initialization
  275:     my $Str;
  276:     $Str .= &Apache::lonhtmlcommon::breadcrumbs
  277:         (undef,'Correct Problems Plot');
  278:     $Str .= '<table cellspacing="5">'."\n";
  279:     $Str .= '<tr>';
  280:     $Str .= '<td align="center"><b>'.&mt('Sections').'</b></td>';
  281:     $Str .= '<td align="center"><b>'.&mt('Enrollment Status').'</b></td>';
  282:     $Str .= '<td align="center"><b>'.&mt('Sequences and Folders').'</b></td>';
  283:     $Str .= '<td rowspan="2">'.
  284:         &Apache::lonstathelpers::limit_by_time_form().'</td>';
  285:     $Str .= '</tr>'."\n";
  286:     ##
  287:     ## 
  288:     $Str .= '<tr><td align="center">'."\n";
  289:     $Str .= &Apache::lonstatistics::SectionSelect('Section','multiple',5);
  290:     $Str .= '</td>';
  291:     #
  292:     $Str .= '<td align="center">';
  293:     $Str .= &Apache::lonhtmlcommon::StatusOptions(undef,undef,5);
  294:     $Str .= '</td><td>'."\n";
  295:     #
  296:     my $only_seq_with_assessments = sub { 
  297:         my $s=shift;
  298:         if ($s->{'num_assess'} < 1) { 
  299:             return 0;
  300:         } else { 
  301:             return 1;
  302:         }
  303:     };
  304:     $Str .= &Apache::lonstatistics::MapSelect('Maps','multiple,all',5,
  305:                                               $only_seq_with_assessments);
  306:     $Str .= '</td>';
  307:     #
  308:     ##
  309:     $Str .= '</tr>'."\n";
  310:     $Str .= '</table>'."\n";
  311:     return $Str;
  312: }
  313: 
  314: 1;
  315: 
  316: __END__

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