File:  [LON-CAPA] / loncom / interface / statistics / lonpercentage.pm
Revision 1.8: download - view: text, annotated - select for diffs
Tue Jan 14 22:10:08 2003 UTC (21 years, 3 months ago) by minaeibi
Branches: MAIN
CVS tags: version_0_6_2, version_0_6_1, HEAD
To fix the reopened bug #1152 a minor change has been done.
If a student has 125 correct out of 125 possible, that is 100%,
he was not included on the plot but NOW it is included.

# The LearningOnline Network with CAPA
# (Publication Handler
#
# $Id: lonpercentage.pm,v 1.8 2003/01/14 22:10:08 minaeibi Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#
###

package Apache::lonpercentage;

use strict;
use Apache::lonhtmlcommon;
use Apache::loncoursedata;
use GDBM_File;


sub BuildPercentageGraph {
    my ($cacheDB, $students, $courseID, $c, $r)=@_;

    my %cache;
    unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER(),0640)) {
        $r->print('Unable to tie database.6');
        return;
    }

    $r->print(&CreateInterface(\%cache));
    $r->rflush();
    untie(%cache);

    my ($result) = &InitializeSelectedStudents($cacheDB, $students, 
					       $courseID, $c, $r);
    if($result ne 'OK' || $c->aborted()) {
        return;
    }

    unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER(),0640)) {
        $r->print('Unable to tie database.6');
        return;
    }

    my ($Ptr, $percentage) = &GraphData(\%cache, $students,$r);
    $r->print($Ptr.'<br>');

    $r->print(&TableData(\%cache, $percentage));

    untie(%cache);

    return;
}

sub CreateInterface {
    my ($cache)=@_;

    my $Ptr = '';
    $Ptr .= '<table border="0" cellspacing="5"><tbody>';
    $Ptr .= '<tr><td align="right"><b>Select Map</b></td>'."\n";
    $Ptr .= '<td align="left">';
    $Ptr .= &Apache::lonhtmlcommon::MapOptions($cache, 'Statistics',
                                               'Statistics');
    $Ptr .= '</td>'."\n";

    my $sequence = $cache->{'StatisticsMaps'};
    if($sequence ne 'All Maps') {
	$Ptr .= '<td align="right">'."\n";
	$Ptr .= &Apache::lonhtmlcommon::ProblemOptions($cache,
						       'Statistics',
						       $sequence,
						       'Statistics');
	$Ptr .= '<td>'."\n";

	my $problem = $cache->{'StatisticsProblemSelect'};
	if($problem ne 'All Problems') {
	    my $parts = &GetParts($cache, $sequence, $problem);
	    if(scalar(@$parts) > 0) {
		$Ptr .= '<td align="right">'."\n";
		$Ptr .= &Apache::lonhtmlcommon::PartOptions($cache,
							'Statistics',
							$parts,
							'Statistics');
		$Ptr .= '</td>'."\n";
	    }
	}
    }

    $Ptr .= '</tr>'."\n";

    $Ptr .= '<tr><td align="right"><b>Select Sections</b>';
    $Ptr .= '</td>'."\n";
    $Ptr .= '<td align="left">'."\n";
    my @sections = split(':',$cache->{'sectionList'});
    my @sectionsSelected = split(':',$cache->{'sectionsSelected'});
    $Ptr .= &Apache::lonhtmlcommon::MultipleSectionSelect(\@sections,
                                                          \@sectionsSelected,
                                                          'Statistics');
    $Ptr .= '</td></tr>'."\n";
    $Ptr .= '</table>';

    return $Ptr;
}

sub GetParts {
    my ($cache,$sequence,$problem)=@_;
    my @parts = ();

    foreach my $sequenceNumber (split(':',$cache->{'orderedSequences'})) {
	if($cache->{$sequenceNumber.':title'} eq $sequence) {
	    foreach my $problemNumber (split(':', 
				     $cache->{$sequenceNumber.':problems'})) {
		if($cache->{$problemNumber.':title'} eq $problem) {
		    @parts = split(':', 
		       $cache->{$sequenceNumber.':'.$problemNumber.':parts'});
		}
	    }
	}
    }
    
    return \@parts;
}

sub InitializeSelectedStudents {
    my ($cacheDB, $students, $courseID, $c, $r)=@_;
    my %cache;

    unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER(),0640)) {
        $r->print('Unable to tie database1.1.');
        return ('ERROR');
    }

    # Remove students who don't have the proper section.
    my @sectionsSelected = split(':',$cache{'sectionsSelected'});
    for(my $studentIndex=((scalar @$students)-1); $studentIndex>=0;
        $studentIndex--) {
        my $value = $cache{$students->[$studentIndex].':section'};
        my $found = 0;
        foreach (@sectionsSelected) {
            if($_ eq 'none') {
                if($value eq '' || !defined($value) || $value eq ' ') {
                    $found = 1;
                    last;
                }
            } else {
                if($value eq $_) {
                    $found = 1;
                    last;
                }
            }
        }
        if($found == 0) {
            splice(@$students, $studentIndex, 1);
        }
    }

    untie(%cache);

    &Apache::loncoursedata::DownloadStudentCourseDataSeparate($students,
							      'true',
							      $cacheDB,
							      'true', 
							      'true',
							      $courseID,
							      $r, $c);

    return ('OK');
}

sub GraphData {
    my ($cache,$students,$r)=@_;

    my $sequenceSelected = $cache->{'StatisticsMaps'};
    my $problemSelected  = $cache->{'StatisticsProblemSelect'};
    my $partSelected     = $cache->{'StatisticsPartSelect'};

    my %percentages;
    my $Ptr = '';
    my $totalProblems = 0;

    foreach(@$students) {
	my $totalCorrect = 0;
        $totalProblems = 0;

	foreach my $sequence (split(':',$cache->{'orderedSequences'})) {
	    next if($cache->{$sequence.':title'} ne $sequenceSelected &&
		    $sequenceSelected ne 'All Maps');
	    foreach my $problem (split(':',$cache->{$sequence.':problems'})) {
		next if($cache->{$problem.':title'} ne $problemSelected &&
			$problemSelected ne 'All Problems' && 
			$sequenceSelected ne 'All Maps');
		foreach my $part (split(':',$cache->{$sequence.':'.$problem.
						     ':parts'})) {
		    next if($part ne $partSelected && 
			    $partSelected ne 'All Parts' &&
			    $problemSelected ne 'All Problems' && 
			    $sequenceSelected ne 'All Maps');
		    my $code = $cache->{$_.':'.$problem.':'.$part.':code'};
		    if($code eq '*' || $code eq '+') {
			$totalCorrect++;
			$totalProblems++;
		    } elsif($code ne 'x') {
			$totalProblems++;
		    }
		}
	    }
	}
	my $percent;
	if ( $totalProblems >= 100 ) { 
            $percent = sprintf("%d", ($totalProblems) ?
                              (($totalCorrect/$totalProblems)*100) : 0);
	} else {
	    $percent = sprintf("%d", ($totalProblems) ? $totalCorrect : 0);
	}
	if(defined($percentages{$percent})) {
	    $percentages{$percent} .= ':::'.$_;
	} else {
	    $percentages{$percent} = $_;
	}
    }

    my @percent = ();
    my @percentCount = ();
    my $max = 0;
    my $pno = 0;

    foreach my $key (sort NumericSort keys(%percentages)) {
	push(@percent, $key);
	my @temp = split(':::', $percentages{$key});
	my $count = scalar(@temp);
	if($count > $max) {
	    $max = $count;
	}
	push(@percentCount, $count);
	$pno++;
    }

    my $cId=0;
    my @data1=();
    my @data2=();
    for (my $nIdx=0; $nIdx<$pno; $nIdx++ ) {
	$data1[$cId]=$percent[$nIdx];
        $data2[$cId]=$percentCount[$nIdx];
	my $cr=$percent[$nIdx+1];
	while ($data1[$cId]<$cr) {
	    $cId++;
            $data1[$cId]=$cId;
            $data2[$cId]=0;
        }
    }

    my $xlabel;
    my $Freq;
    if ($totalProblems >= 100 ) {
        $xlabel = 'Percentage_of_Problems_Correct';
        $Freq=101;
    } else {
        $xlabel = 'Number_of_Problems_Correct';
        $Freq = $cId;
    }

#   $r->print('<br>Freq='.$Freq);
#   $r->print('<br>max='.$max);
#   $r->print('<br> percentcount='.join(',', @percentCount)); 
#   $r->print('<br> percent='.join(',', @percent));
#   $r->print('<br> percentcount='.join(',', @data1));
#   $r->print('<br> percent='.join(',', @data2));

    my @GData = ("Percentage",$xlabel,
                 'Number_of_Students',$max,$Freq,
                 join(',',@data1), join(',', @data2));

    $Ptr .= '</form>'."\n";
    $Ptr .= '<IMG src="/cgi-bin/graph.png?'.(join('&', @GData));
    $Ptr .= '" border="1" />';
    $Ptr .= '<form>'."\n";

    return ($Ptr, \%percentages);
}

sub NumericSort {
    $a <=> $b;
}

sub TableData {
    my($cache,$percentage)=@_;
    my $Ptr;

    $Ptr .= '<table border="0"><tr><td bgcolor="#D7D7D7">'."\n";
    $Ptr .= '<table border="0" cellpadding="3"><tr bgcolor="#e6ffff">'."\n";

    $Ptr .= '<tr>'."\n";
    $Ptr .= '<td>% Correct</td>'.
            '<td>Frequency</td>'.
            '<td>Students</td>';
    $Ptr .= '</tr>'."\n";

    my $alternate=0;
    foreach (sort NumericSort keys(%$percentage)) {

        my @temp = split(':::', $percentage->{$_});
        my $count = scalar(@temp);

        if($alternate) {
            $Ptr .= '<tr bgcolor="#ffffe6">';
        } else {
            $Ptr .= '<tr bgcolor="#ffffc6">';
        }
        $alternate = ($alternate + 1) % 2;

	$Ptr .= '<td>'.$_.'</td>';
        $Ptr .= '<td>'.$count.'</td><td>';

	foreach my $name (sort(split(':::', $percentage->{$_}))) {
	    $Ptr .= '<a href="/adm/statistics?reportSelected=';
	    $Ptr .= &Apache::lonnet::escape('Student Assessment');
	    $Ptr .= '&StudentAssessmentStudent=';
	    $Ptr .= &Apache::lonnet::escape($cache->{$name.':fullname'}).'">';
	    $Ptr .= $cache->{$name.':fullname'};
	    $Ptr .= '</a>,&nbsp&nbsp';
        }

	$Ptr .= '</td></tr>'."\n";
    }

    $Ptr .= '</tr>'."\n";
    $Ptr .= '</table></td></tr></table>'."\n";

    return $Ptr;
}

1;
__END__

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