--- loncom/interface/lonquickgrades.pm 2024/07/03 18:51:56 1.49.6.9
+++ loncom/interface/lonquickgrades.pm 2024/12/10 04:52:30 1.128
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Quick Student Grades Display
#
-# $Id: lonquickgrades.pm,v 1.49.6.9 2024/07/03 18:51:56 raeburn Exp $
+# $Id: lonquickgrades.pm,v 1.128 2024/12/10 04:52:30 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -35,8 +35,26 @@ use Apache::loncommon;
use Apache::lonlocal;
use Apache::lonnet;
use Apache::grades;
+use Apache::loncoursedata;
+use Apache::lonstudentassessment;
use Apache::lonuserstate;
+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 {
my $r = shift;
return real_handler($r);
@@ -60,7 +78,8 @@ sub real_handler {
my $cangrade=&Apache::lonnet::allowed('mgr');
my $showPoints =
- $env{'course.'.$env{'request.course.id'}.'.grading'} eq 'standard';
+ (($env{'course.'.$env{'request.course.id'}.'.grading'} eq 'standard')
+ || ($env{'course.'.$env{'request.course.id'}.'.grading'} eq 'categories'));
my $reinitresult;
@@ -85,7 +104,7 @@ sub real_handler {
unless ($cangrade) {
# Check for critical messages and redirect if present.
- my ($redirect,$url) = &Apache::loncommon::critical_redirect(300);
+ my ($redirect,$url) = &Apache::loncommon::critical_redirect(300,'grades');
if ($redirect) {
&Apache::loncommon::content_type($r,'text/html');
$r->header_out(Location => $url);
@@ -101,10 +120,14 @@ sub real_handler {
$r->send_http_header;
$r->print(&Apache::loncommon::check_release_result(@reinit));
return OK;
- } elsif ($reinitresult eq 'update') {
- my $cid = $env{'request.course.id'};
- my $cnum = $env{'course.'.$cid.'.num'};
- my $cdom = $env{'course.'.$cid.'.domain'};
+ }
+ my ($cid,$cnum,$cdom);
+ if ($reinitresult) {
+ $cid = $env{'request.course.id'};
+ $cnum = $env{'course.'.$cid.'.num'};
+ $cdom = $env{'course.'.$cid.'.domain'};
+ }
+ if (($reinitresult eq 'main') || ($reinitresult eq 'both')) {
&Apache::loncommon::content_type($r,'text/html');
$r->send_http_header;
&startpage($r,$showPoints);
@@ -113,11 +136,11 @@ sub real_handler {
&mt('Your course session is being updated because of recent changes by course personnel.').
' '.&mt('Please be patient').'.
'.
'
'.&mt('Sections').''. + &Apache::loncommon::help_open_topic("Chart_Sections"). + ' | '. + ''.&mt('Groups').''. + ' | '. + ''.&mt('Student Data').''. + &Apache::loncommon::help_open_topic("Chart_Student_Data"). + ' | '. + ''.&mt('Access Status').''. + &Apache::loncommon::help_open_topic("Chart_Enrollment_Status"). + ' | '. + ''.&mt('Output Format').''. + &Apache::loncommon::help_open_topic("Chart_Output_Formats"). + ' | |
'."\n". + &Apache::lonstatistics::SectionSelect('Section','multiple',5). + ' | '. + &Apache::lonstatistics::GroupSelect('Group','multiple',5). + ' | '. + &Apache::lonstatistics::StudentDataSelect('StudentData','multiple',5,undef). + ' | '."\n". + &Apache::lonhtmlcommon::StatusOptions(undef,undef,5). + ' | '."\n". + &Apache::lonstudentassessment::CreateAndParseOutputSelector(). + ' | '. + ''. + ' |
'.&mt('Full Name: [_1]',&Apache::loncommon::plainname($uname,$udom)).'
'); } - } else { - $r->print(''.&mt('This may take a few moments to display.').'
'); } $r->rflush(); my $notshowTotals= $env{'course.'.$env{'request.course.id'}.'.grading'} eq 'externalnototals'; + my $showCategories= + $env{'course.'.$env{'request.course.id'}.'.grading'} eq 'categories'; + + my $usec; + if ($cangrade) { + if (($uname eq $env{'user.name'}) && ($udom eq $env{'user.domain'})) { + $usec = $env{'request.course.sec'}; + } else { + $usec = &Apache::lonnet::getsection($udom,$uname,$env{'request.course.id'}); + } + } else { + $usec = $env{'request.course.sec'}; + } my ($navmap,$totalParts,$totalPossible,$totalRight,$totalAttempted,$topLevelParts, - $topLevelRight,$topLevelAttempted) = &getData($showPoints,$uname,$udom); + $topLevelRight,$topLevelAttempted) = &getData($showPoints,$uname,$udom,$usec); if (ref($navmap)) { - my $nostdtotals; - if ($showPoints) { - if ($env{'course.'.$env{'request.course.id'}.'.grading'} eq 'standard') { - my $hidetotals = $env{'course.'.$env{'request.course.id'}.'.hidetotals'}; - if ($hidetotals eq 'all') { - $nostdtotals = 1; - } elsif ($hidetotals ne '') { - my $usec; - if ($cangrade) { - if (($uname eq $env{'user.name'}) && ($udom eq $env{'user.domain'})) { - $usec = $env{'request.course.sec'}; - } else { - $usec = &Apache::lonnet::getsection($udom,$uname,$env{'request.course.id'}); - } - } else { - $usec = $env{'request.course.sec'}; - } - if ($usec ne '') { - my %secnototals; - map { $secnototals{$_} = 1; } split(/,/,$hidetotals); - if ($secnototals{$usec}) { - $nostdtotals = 1; + if ($showCategories) { + &outputCategories($r,$showPoints,$notshowTotals,$navmap,$totalParts,$totalPossible, + $totalRight,$totalAttempted,$topLevelParts,$topLevelRight, + $topLevelAttempted); + } else { + my $nostdtotals; + if ($showPoints) { + if ($env{'course.'.$env{'request.course.id'}.'.grading'} eq 'standard') { + my $hidetotals = $env{'course.'.$env{'request.course.id'}.'.hidetotals'}; + if ($hidetotals eq 'all') { + $nostdtotals = 1; + } elsif ($hidetotals ne '') { + if ($usec ne '') { + my %secnototals; + map { $secnototals{$_} = 1; } split(/,/,$hidetotals); + if ($secnototals{$usec}) { + $nostdtotals = 1; + } } } } } + &outputTable($r,$showPoints,$notshowTotals,$nostdtotals,$navmap, + $totalParts,$totalPossible,$totalRight,$totalAttempted, + $topLevelParts,$topLevelRight,$topLevelAttempted); } - &outputTable($r,$showPoints,$notshowTotals,$nostdtotals,$navmap, - $totalParts,$totalPossible,$totalRight,$totalAttempted, - $topLevelParts,$topLevelRight,$topLevelAttempted); } else { if ($cangrade) { $r->print("\n\n"); } my $requrl = $r->uri; @@ -257,16 +336,208 @@ sub grades_blocked { return; } +sub getStudentCatGrade { + my ($uname,$udom,$usec,%categories)=@_; + my ($navmap,$totalParts,$totalPossible,$totalRight,$totalAttempted,$topLevelParts,$topLevelRight,$topLevelAttempted)= + &getData(1,$uname,$udom,$usec); + 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(); + my $sectionidx = &Apache::loncoursedata::CL_SECTION(); + + foreach my $key (keys(%{$classlist})) { + my $student = $classlist->{$key}; + my $perc=&getStudentCatGrade($classlist->{$student}->[$usernameidx], + $classlist->{$student}->[$domainidx], + $classlist->{$student}->[$sectionidx], + %categories); + } +} + +sub startpage { + my ($r,$showPoints) = @_; + 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}) + ); +} + +sub startGradeScreen { + my ($r,$mode)=@_; + + my $showPoints = + $env{'course.'.$env{'request.course.id'}.'.grading'} eq 'standard'; + my $hidetotals = + $env{'course.'.$env{'request.course.id'}.'.hidetotals'}; + my $notshowSPRSlink = + (($env{'course.'.$env{'request.course.id'}.'.grading'} eq 'external') + || ($env{'course.'.$env{'request.course.id'}.'.grading'} eq 'externalnototals') + || ($env{'course.'.$env{'request.course.id'}.'.grading'} eq 'categories')); + my $notshowTotals = + $env{'course.'.$env{'request.course.id'}.'.grading'} eq 'externalnototals'; + my $showSPRSlink = + $env{'course.'.$env{'request.course.id'}.'.grading'} eq 'spreadsheet'; + my $showCategories = + $env{'course.'.$env{'request.course.id'}.'.grading'} eq 'categories'; + + my $allowed_to_view = &Apache::lonnet::allowed('vgr',$env{'request.course.id'}); + if ((!$allowed_to_view) && ($env{'request.course.sec'} ne '')) { + $allowed_to_view = &Apache::lonnet::allowed('vgr', + "$env{'request.course.id'}/$env{'request.course.sec'}"); + } + + my $allowed_to_edit = &Apache::lonnet::allowed('mgr',$env{'request.course.id'}); + if ((!$allowed_to_edit) && ($env{'request.course.sec'} ne '')) { + $allowed_to_edit = &Apache::lonnet::allowed('mgr', + "$env{'request.course.id'}/$env{'request.course.sec'}"); + } + + 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); + if (($showPoints) && ($hidetotals ne '')) { + if ($hidetotals eq 'all') { + push(@notes,&mt('Students do not see course totals.')); + } else { + my @secs = split(/,/,$hidetotals); + if (@secs == 1) { + push(@notes,&mt('Students in section [_1] do not see course totals.', + $hidetotals)); + } elsif (@secs > 1) { + push(@notes,&mt('Students in sections [_1] do not see course totals.', + join(', ',@secs))); + } + } + } + push(@notes,&mt('Students will see points based on categories.')) if ($showCategories); + push(@notes,&mt('Students will see link to spreadsheet.')) if ($showSPRSlink); + push(@notes, &Apache::lonhtmlcommon::coursepreflink(&mt('Grade display settings'),'grading')); + $r->print(&Apache::loncommon::head_subbox(join(' ',@notes))); + } + + + $r->print("\n".''.&mt('Total raw points: [_1]/[_2]',&numberout($totalcorrect),&numberout($totalpossible)).'
'); + $r->print(''.&mt('Adjusted raw points: [_1]/[_2]',&numberout($totalcorrect),&numberout($totalpossible)).'
'); + } + + +# Calculation + if ($output) { $r->print(''.&mt('Calculated points: [_1]/[_2]',&numberout($totalcorrect),&numberout($totalpossible)).'
'); + $r->print(''); + if ($type eq 'percent') { + my $perc='---'; + if ($totalpossible) { + $perc=100.*$totalcorrect/$totalpossible; + } + $r->print(&mt('[_1] percent',&numberout($perc))); + } else { + $r->print(&mt('[_1]/[_2] points',&numberout($totalcorrect),&numberout($totalpossible))); + } + $r->print('
'); + } + if ($output) { $r->print('