--- loncom/interface/lonwhatsnew.pm 2005/04/18 20:35:07 1.11 +++ loncom/interface/lonwhatsnew.pm 2005/09/21 18:20:22 1.31 @@ -1,5 +1,5 @@ # -# $Id: lonwhatsnew.pm,v 1.11 2005/04/18 20:35:07 raeburn Exp $ +# $Id: lonwhatsnew.pm,v 1.31 2005/09/21 18:20:22 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -35,8 +35,10 @@ use Apache::lonhtmlcommon(); use Apache::lonlocal; use Apache::loncoursedata(); use Apache::lonnavmaps(); +use Apache::lonuserstate; use Apache::Constants qw(:common :http); use Time::Local; +use GDBM_File; #---------------------------- # handler @@ -52,10 +54,13 @@ sub handler { } &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['command']); - my $command = $env{'form.command'}; - - if ($command eq '') { - $command = "info"; + my $command; + if ($env{'form.action'} eq 'reset') { + $command = 'reset'; + } elsif ($env{'form.action'} eq 'update') { + $command = 'update'; + } else { + $command = $env{'form.command'}; } &Apache::loncommon::content_type($r,'text/html'); @@ -68,20 +73,21 @@ sub handler { } &Apache::lonhtmlcommon::clear_breadcrumbs(); - if ($command eq 'config') { + if ($command eq 'chgthreshold') { &Apache::lonhtmlcommon::add_breadcrumb - ({href=>'/adm/whatsnew?command=config', - text=>"Configure display"}); + ({href=>'/adm/whatsnew?command=threshold', + text=>"Change thresholds"}); $r->print(&Apache::lonhtmlcommon::breadcrumbs - (undef,'Course Action Items','Course_Action_Items_Config')); + (undef,'Course Action Items','Course_Action_Items_Thresholds')); } else { &Apache::lonhtmlcommon::add_breadcrumb - ({href=>'/adm/whatsnew?command=info', + ({href=>'/adm/whatsnew', text=>"Display Action Items"}); $r->print(&Apache::lonhtmlcommon::breadcrumbs (undef,'Course Action Items','Course_Action_Items_Display')); } &display_main_box($r,$command); + return OK; } #------------------------------ @@ -94,30 +100,20 @@ sub display_main_box { my ($r,$command) = @_; my $domain=&Apache::loncommon::determinedomain(); my $tabbg=&Apache::loncommon::designparm('coordinator.tabbg',$domain); - my $selconfig; - my $selinfo; - if ($command eq 'config') { - $selinfo = 'selected="selected"'; - } else { - $selconfig = 'selected="selected"'; - } - my $picker = (' -<form> - <nobr> - <input type="submit" value="'.&mt('Change page to:').'" /> - <select name="command"> - <option value="info" '.$selinfo.'">'.&mt('Display Action Items').'</option> - <option value="config" '.$selconfig.'">'.&mt('Configure Settings').'</option> - </select> - </nobr> -</form>'); - $r->print('<table width="100%" border="0" cellpadding="5" cellspacing="0"><tr><td width="100%">'); - - if ($command eq 'config') { - &display_config_box($r,$picker); + + my %threshold_titles = ( + av_attempts => 'Average number of attempts', + degdiff => 'Degree of difficulty', + numstudents => 'Total number of students with submissions', + ); + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $crs = $env{'course.'.$env{'request.course.id'}.'.num'}; + + if ($command eq 'chgthreshold') { + &display_config_box($r,$command,$tabbg,\%threshold_titles,$cdom,$crs); } else { - &display_actions_box($r,$picker); + &display_actions_box($r,$command,\%threshold_titles,$cdom,$crs); } $r->print(<<END_OF_BLOCK); </td> @@ -155,7 +151,7 @@ ENDHEAD #------------------------------- sub display_actions_box() { - my ($r,$picker) = @_; + my ($r,$command,$threshold_titles,$cdom,$crs) = @_; my $rowColor1 = "#ffffff"; my $rowColor2 = "#eeeeee"; @@ -171,6 +167,7 @@ sub display_actions_box() { my @tograde = (); my @bombs = (); my @warnings = (); + my %res_title = (); my $domain=&Apache::loncommon::determinedomain(); my $function; @@ -181,18 +178,43 @@ sub display_actions_box() { $function='admin'; } + my %threshold = ( + av_attempts => 2, + degdiff => 0.5, + numstudents => 2, + ); + my $pgbg=&Apache::loncommon::designparm($function.'.pgbg',$domain); my $tabbg=&Apache::loncommon::designparm($function.'.tabbg',$domain); - &getitems(\%unread,\%ungraded,\%bombed,\%triggered,\@newdiscussions,\@tograde,\@bombs,\@warnings,$rowColor1,$rowColor2); - my ($msgcount,$critmsgcount) = &getmail(\@newmsgs,\@critmsgs); - unless ($env{'request.course.id'}) { - $r->print('<br /><b><center>You are accessing an invalid course</center></b><br /><br />'); + $r->print('<br /><b><center>You are accessing an invalid course.</center></b><br /><br />'); return; } + if (tie(my %bighash,'GDBM_File',$env{'request.course.fn'}.'.db', + &GDBM_READER(),0640)) { + my $furl=$bighash{'first_url'}; + $r->print('<font size="+1"><a href="'.$furl.'">Go to first resource</a></font><a href="/adm/preferences?action=changecourseinit"></font><br />Change your preferences</a> to suppress display of this screen when accessing courses as Course Coordinator in the future.<br /><hr />'); + untie(%bighash); + } + + my $result; + + if ($command eq 'reset') { + $result = &process_reset($cdom,$crs); + } elsif ($command eq 'update') { + $result = &process_update($cdom,$crs,$threshold_titles); + } + if ($result) { + $r->print($result.'<hr width="100%" />'); + } + $r->rflush(); + + &get_curr_thresholds(\%threshold,$cdom,$crs); + &getitems(\%unread,\%ungraded,\%bombed,\%triggered,\@newdiscussions,\@tograde,\@bombs,\@warnings,$rowColor1,$rowColor2,\%threshold,$cdom,$crs,%res_title); + my ($msgcount,$critmsgcount) = &getmail(\@newmsgs,\@critmsgs); - $r->print('<b>'.$picker.'</b><br /><hr width="100%" /><table border="0" width="100%" cellpadding="2" cellspacing="4"><tr><td align="left" valign="top" width="45%">'); + $r->print('<br /><table border="0" width="100%" cellpadding="2" cellspacing="4"><tr><td align="left" valign="top" width="45%">'); ## UNGRADED ITEMS ## $r->print(<<END); @@ -242,14 +264,15 @@ END END my $bombnum = 0; if (@bombs > 0) { -# @bombs = sort { &cmp_title($a,$b) } @bombs; + $r->print('<tr bgcolor="#cccccc"><td><b><small>Resource</small></b></td><td align="right"><b><small>Number of errors</small></b></td></tr>'); + @bombs = sort { &cmp_title($a,$b,\%res_title) } @bombs; foreach my $bomb (@bombs) { if ($bombnum %2 == 1) { - $rowColor = $rowColor1; + $rowColor = $rowColor1; } else { $rowColor = $rowColor2; } - $r->print('<tr bgcolor="'.$rowColor.'"><td>'.$bombed{$bomb}{errorlink}.'</td></tr>'); + $r->print('<tr bgcolor="'.$rowColor.'"><td><small>'.$bombed{$bomb}{errorlink}.'</small></td><td align="right"><small>'.$bombed{$bomb}{errorcount}.'</small></td></tr>'); $bombnum ++; } } else { @@ -258,25 +281,30 @@ END $r->print('</table></td></tr></table></td></tr></table><br />'); # DEGDIFF AND AV. TRIES TRIGGERS - $r->print(<<"END"); + $r->print(<<"END"); <table border="0" cellpadding="0" cellspacing="0" bgcolor="#000000" width="100%"> <tr> <td> <table border="0" cellpadding="1" cellspacing="1" bgcolor="#000000" width="100%"> <tr> - <td bgcolor="$tabbg"><b>Problems with average attempts > 0 or degree of difficulty > 0</b></td> + <td bgcolor="$tabbg"><b>Problems with av. attempts ≥ $threshold{'av_attempts'} or deg. difficulty ≥ $threshold{'degdiff'}<br /> and total number of students with submissions ≥ $threshold{'numstudents'}</b></td> + </tr> + <tr> + <td bgcolor="$tabbg" align="right"><a href="/adm/whatsnew?command=chgthreshold"><b><small>Change thresholds?</small></b></a></td> </tr> <tr> <td bgcolor="#ffffff"> - <table width="100%" cellspacing="0" cellpadding="0" border="0"> + <table width="100%" cellspacing="2" cellpadding="2" border="0"> END - my $warningnum = 0; - if (@warnings > 0) { -# @warnings = sort { &cmp_title($a,$b) } @warnings; - $r->print('<tr bgcolor="#cccccc"><td><b><small>Resource</small></b></td><td align="right"><b><small>Part</small></b><td align="right"><b><small>Num. students</small></b></td><td align="right"><b><small>Av. Attempts</small></b></td><td align="right"><b><small>Deg. Diff</small></b></td></tr>'); + my $warningnum = 0; + if (@warnings > 0) { + @warnings = sort { &cmp_title($a,$b,\%res_title) } @warnings; + $r->print('<form name="reset_tracking" method="post">'. + ' <input type="hidden" name="action" value="reset" />'."\n"); + $r->print('<tr bgcolor="#cccccc"><td><b><small>Resource</small></b></td><td align="right"><b><small>Part</small></b></td><td align="right"><b><small>Num. students</small></b></td><td align="right"><b><small>Av. Attempts</small></b></td><td align="right"><b><small>Deg. Diff</small></b></td><td align="right"><b><small>Last Reset</small></b></td><td align="right"><b><small>Reset Count?</small></b></td></tr>'); foreach my $res (@warnings) { if ($warningnum %2 == 1) { - $rowColor = $rowColor1; + $rowColor = $rowColor1; } else { $rowColor = $rowColor2; } @@ -290,8 +318,9 @@ END $r->print('<tr bgcolor="'.$rowColor.'"><td '.$rowspan.'><a href="'.$linkurl.'"><small>'.$triggered{$res}{title}.'</small></a></td>'.$triggered{$res}{text}); $warningnum ++; } + $r->print('<tr bgcolor="#cccccc"><td colspan="7" align="right"><br /><b><small><input type="submit" name="counters" value="Reset counters to 0" /></form>'); } else { - $r->print('<tr><td bgcolor="#ffffff"><br /><center><b><i><small>No problems with av. attempts or degree of difficulty above thresholds</small></i></b></center><br /></td></tr>'); + $r->print('<tr><td bgcolor="#ffffff"><br /><center><b><i><small>No problems satisfy threshold criteria.</small></i></b></center><br /></td></tr>'); } $r->print('</table></td></tr></table></td></tr></table><br />'); @@ -312,7 +341,7 @@ END if (@newdiscussions > 0) { $r->print('<tr bgcolor="#cccccc"><td><b><small>Location</small></b></td><td><b><small>Type</small></b><td align="right"><b><small>Number of new posts</small></b></td></tr>'); -# @newdiscussions = sort { &cmp_title($a,$b) } @newdiscussions; + @newdiscussions = sort { &cmp_title($a,$b,\%res_title) } @newdiscussions; my $rowNum = 0; foreach my $ressymb (@newdiscussions) { my $forum_title = $unread{$ressymb}{'title'}; @@ -361,7 +390,7 @@ END } else { $rowColor = $rowColor2; } - $r->print('<tr bgcolor="'.$rowColor.'"><td valign="top"><small>'.$mailcount.'. <small></td><td valign="top"><small><a href="/adm/mail?">'.$msg->{'shortsub'}.'</a> </small></td><td valign="top"><small> '.$msg->{'from'}.'@'.$msg->{'fromdom'}.' </small></td><td valign="top"><small>'.$msg->{'sendtime'}.'</small></td></tr>'); + $r->print('<tr bgcolor="'.$rowColor.'"><td valign="top"><small>'.$mailcount.'. </small></td><td valign="top"><small><a href="/adm/communicate">'.$msg->{'shortsub'}.'</a> </small></td><td valign="top"><small> '.$msg->{'from'}.'@'.$msg->{'fromdom'}.' </small></td><td valign="top"><small>'.$msg->{'sendtime'}.'</small></td></tr>'); $rowNum ++; $mailcount ++; } @@ -393,7 +422,7 @@ END } else { $rowColor = $rowColor2; } - $r->print('<tr bgcolor="'.$rowColor.'"><td valign="top"><small>'.$mailcount.'. <small></td><td valign="top"><small><a href="/adm/mail?">'.$msg->{'shortsub'}.'</a> </small></td><td valign="top"><small> '.$msg->{'from'}.'@'.$msg->{'fromdom'}.' </small></td><td valign="top"><small>'.$msg->{'sendtime'}.'</small></td></tr>'); + $r->print('<tr bgcolor="'.$rowColor.'"><td valign="top"><small>'.$mailcount.'. <small></td><td valign="top"><small><a href="/adm/email?folder=critical">'.$msg->{'shortsub'}.'</a> </small></td><td valign="top"><small> '.$msg->{'from'}.'@'.$msg->{'fromdom'}.' </small></td><td valign="top"><small>'.$msg->{'sendtime'}.'</small></td></tr>'); $rowNum ++; $mailcount ++; } @@ -414,33 +443,82 @@ END #------------------------------- # display_config_box # -# Display the action items +# Display the threshold setting screen # #------------------------------- sub display_config_box() { - my ($r,$picker) = @_; - $r->print('<b>'.$picker.'</b><br /><hr width="100%" /><table border="0" width="100%" cellpadding="2" cellspacing="4"><tr><td align="left" valign="top" width="45%">'); + my ($r,$command,$tabbg,$threshold_titles,$cdom,$crs) = @_; + my %threshold = (); + my $rowColor1 = "#ffffff"; + my $rowColor2 = "#eeeeee"; + my $rowColor; + + my @thresholditems = ("av_attempts","degdiff","numstudents"); + my %threshold_titles = ( + av_attempts => 'Average number of attempts', + degdiff => 'Degree of difficulty', + numstudents => 'Total number of students with submissions', + ); + &get_curr_thresholds(\%threshold,$cdom,$crs); + + $r->print('<br /><form name="thresholdform" method="post"><table border="0" cellpadding="2" cellspacing="4"><tr><td align="left" valign="top" width="45%"> + <table border="0" cellpadding="0" cellspacing="0" bgcolor="#000000"> + <tr> + <td> + <table border="0" cellpadding="1" cellspacing="1" bgcolor="#000000"> + <tr> + <td bgcolor="#ffffff"> + <table cellspacing="0" cellpadding="4" border="0"> + <tr bgcolor="'.$tabbg.'"> + <th>Threshold Name</th> + <th>Current value</th> + <th>Change?</th> + </tr>'); + my $rowNum =0; + foreach my $type (@thresholditems) { + my $parameter = 'internal.threshold_'.$type; +# onchange is javascript to automatically check the 'Set' button. + my $onchange = 'onFocus="javascript:window.document.forms'. + "['thresholdform'].elements['".$parameter."_setparmval']". + '.checked=true;"'; + if ($rowNum %2 == 1) { + $rowColor = $rowColor1; + } else { + $rowColor = $rowColor2; + } + $r->print(' + <tr bgcolor="'.$rowColor.'"> + <td>'.$threshold_titles{$type}.'</td> + <td>'.&Apache::lonhtmlcommon::textbox($parameter.'_value', + $threshold{$type}, + 10,$onchange).'</td> + <td>' + .&Apache::lonhtmlcommon::checkbox($parameter.'_setparmval'). + '</td> + </tr>'); + $rowNum ++; + } + $r->print('</table></td></tr></table></td></tr></table> + <br /><input type="submit" name="threshold" value="Make changes" /> + <input type="hidden" name="action" value="update" /> + </form>'); } sub getitems { - my ($unread,$ungraded,$bombed,$triggered,$newdiscussions,$tograde,$bombs,$warnings,$rowColor1,$rowColor2) = @_; + my ($unread,$ungraded,$bombed,$triggered,$newdiscussions,$tograde,$bombs,$warnings,$rowColor1,$rowColor2,$threshold,$cdom,$crs,$res_title) = @_; my $navmap = Apache::lonnavmaps::navmap->new(); - my @allres=$navmap->retrieveResources(); - my %discussiontime = &Apache::lonnet::dump('discussiontimes', - $env{'course.'.$env{'request.course.id'}.'.domain'}, - $env{'course.'.$env{'request.course.id'}.'.num'}); - my %lastread = &Apache::lonnet::dump('nohist_'.$env{'request.course.id'}.'_discuss',$env{'user.domain'},$env{'user.name'},'lastread'); + # force retrieve Resource to seed the part id cache we'll need it later + my @allres=$navmap->retrieveResources(undef,sub {if ($_[0]->is_problem) { $_[0]->parts();} return 1;}); + my %discussiontime = &Apache::lonnet::dump('discussiontimes',$cdom,$crs); + my %lastread = &Apache::lonnet::dump('nohist_'.$env{'request.course.id'}. + '_discuss',$env{'user.domain'},$env{'user.name'},'lastread'); my %lastreadtime = (); my @discussions = (); my ($classlist,$keylist) = &Apache::loncoursedata::get_classlist(); my %resourcetracker = &Apache::lonnet::dump('nohist_resourcetracker', - $env{'course.'.$env{'request.course.id'}.'.domain'}, - $env{'course.'.$env{'request.course.id'}.'.num'}); - - my $diffcheck = 0; - my $triescheck = 0; + $cdom,$crs); my $warningnum = 0; foreach my $key (keys(%lastread)) { my $newkey = $key; @@ -451,14 +529,15 @@ sub getitems { my $result = ''; my $applies = 0; my $symb = $resource->symb(); - %{$$bombed{$symb}} = (); +# %{$$bombed{$symb}} = (); %{$$ungraded{$symb}} = (); %{$$triggered{$symb}} = (); $$triggered{$symb}{numparts} = 0; my $title = $resource->compTitle(); + $$res_title{$symb} = $title; my $ressymb = $resource->wrap_symb(); # Check for unread discussion postings - if (defined($discussiontime{$ressymb})) { + if ($resource->hasDiscussion()) { push(@discussions,$ressymb); my $prevread = 0; my $unreadcount = 0; @@ -468,9 +547,8 @@ sub getitems { if (defined($lastreadtime{$ressymb})) { $prevread = $lastreadtime{$ressymb}; } - my %contrib = &Apache::lonnet::restore($ressymb,$env{'request.course.id'}, - $env{'course.'.$env{'request.course.id'}.'.domain'}, - $env{'course.'.$env{'request.course.id'}.'.num'}); + my %contrib = &Apache::lonnet::restore($ressymb, + $env{'request.course.id'},$cdom,$crs); if ($contrib{'version'}) { for (my $id=1;$id<=$contrib{'version'};$id++) { unless (($contrib{'hidden'}=~/\.$id\./) || ($contrib{'deleted'}=~/\.$id\./)) { @@ -488,57 +566,71 @@ sub getitems { if ($resource->is_problem()) { my $ctr = 0; my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb); - my ($partlist,$handgrade,$responseType) = &Apache::grades::response_type($url,$symb); - foreach my $student (keys(%$classlist)) { - my ($uname,$udom) = split(/:/,$student); - my %status=&Apache::grades::student_gradeStatus($url,$symb,$udom,$uname,$partlist); - my $submitted = 0; - my $ungraded = 0; - foreach (keys(%status)) { - $submitted = 1 if ($status{$_} ne 'nothing'); - $ungraded = 1 if ($status{$_} =~ /^ungraded/); - my ($foo,$partid,$foo1) = split(/\./,$_); - if ($status{'resource.'.$partid.'.submitted_by'} ne '') { - $submitted = 0; - } - } - next if (!$submitted || !$ungraded); - $ctr ++; - } - if ($ctr) { - $$ungraded{$symb}{count} = $ctr; - $$ungraded{$symb}{title} = $title; - push(@{$tograde}, $symb); - } + my $partlist=$resource->parts(); + my $handgradeable; + foreach my $part (@$partlist) { + if ($resource->handgrade($part) eq 'yes') { + $handgradeable=1; last; + } + } + if ($handgradeable) { + foreach my $student (keys(%$classlist)) { + my ($uname,$udom) = split(/:/,$student); + my %status=&Apache::grades::student_gradeStatus($url,$symb,$udom,$uname,$partlist); + my $submitted = 0; + my $ungraded = 0; + foreach (keys(%status)) { + $submitted = 1 if ($status{$_} ne 'nothing'); + $ungraded = 1 if ($status{$_} =~ /^ungraded/); + my ($foo,$partid,$foo1) = split(/\./,$_); + if ($status{'resource.'.$partid.'.submitted_by'} ne '') { + $submitted = 0; + } + } + next if (!$submitted || !$ungraded); + $ctr ++; + } + if ($ctr) { + $$ungraded{$symb}{count} = $ctr; + $$ungraded{$symb}{title} = $title; + push(@{$tograde}, $symb); + } + } } # Check for bombs if ($resource->getErrors()) { my $errors = $resource->getErrors(); + $errors =~ s/^,//; my @bombs = split(/,/, $errors); my $errorcount = scalar(@bombs); my $errorlink = '<a href="/adm/email?display='. - &Apache::lonnet::escape($$bombs[0]).'">'; + &Apache::lonnet::escape($bombs[0]).'">'. + $title.'</a>'; $$bombed{$symb}{errorcount} = $errorcount; $$bombed{$symb}{errorlink} = $errorlink; push(@{$bombs}, $symb); } -# Compile maxtries and degree of difficulty for problem parts +# Compile maxtries and degree of difficulty for problem parts, unless handgradeable my @parts = @{$resource->parts()}; - my %stats = (); + my %stats; + my %lastreset = (); my $warning = 0; my $rowColor; - foreach (@parts) { - %{$stats{$_}} = (); + foreach my $part (@parts) { + if ($resource->handgrade($part) eq 'yes') { + next; + } + %{$stats{$part}} = (); my ($attempts,$users,$corrects,$degdiff,$av_attempts); - if (exists($resourcetracker{$symb.'_'.$_.'_attempts'})) { - $attempts = $resourcetracker{$symb.'_'.$_.'_attempts'}; + if (exists($resourcetracker{$symb."\0".$part."\0attempts"})) { + $attempts = $resourcetracker{$symb."\0".$part."\0attempts"}; } - if (exists($resourcetracker{$symb.'_'.$_.'_users'})) { - $users = $resourcetracker{$symb.'_'.$_.'_users'}; + if (exists($resourcetracker{$symb."\0".$part."\0users"})) { + $users = $resourcetracker{$symb."\0".$part."\0users"}; } - if (exists($resourcetracker{$symb.'_'.$_.'_correct'})) { - $corrects = $resourcetracker{$symb.'_'.$_.'_correct'}; + if (exists($resourcetracker{$symb."\0".$part."\0correct"})) { + $corrects = $resourcetracker{$symb."\0".$part."\0correct"}; } if ($attempts > 0) { $degdiff = 1 - ($corrects/$attempts); @@ -546,11 +638,13 @@ sub getitems { } if ($users > 0) { $av_attempts = $attempts/$users; + $av_attempts = sprintf("%.2f",$av_attempts); } - if (($degdiff ne '' && $degdiff >= $diffcheck) || ($av_attempts ne '' && $av_attempts >= $triescheck)) { - $stats{$_}{degdiff} = $degdiff; - $stats{$_}{attempts} = $av_attempts; - $stats{$_}{users} = $users; + if ((($degdiff ne '' && $degdiff >= $$threshold{'degdiff'}) || ($av_attempts ne '' && $av_attempts >= $$threshold{'av_attempts'})) && ($users >= $$threshold{'numstudents'})) { + $stats{$part}{degdiff} = $degdiff; + $stats{$part}{attempts} = $av_attempts; + $stats{$part}{users} = $users; + $lastreset{$part} = $resourcetracker{$symb."\0".$part."\0resettime"}; $warning = 1; } } @@ -561,22 +655,26 @@ sub getitems { $rowColor = $rowColor2; } $$triggered{$symb}{title} = $resource->title; - foreach (@parts) { - if (exists($stats{$_}{users})) { + foreach my $part (@parts) { + if (exists($stats{$part}{users})) { + my $resetname = 'reset_'.&Apache::lonnet::escape($symb."\0".$part); + my $resettitle = 'title_'.&Apache::lonnet::escape($symb."\0".$part); if ($$triggered{$symb}{numparts}) { $$triggered{$symb}{text} .= '<tr bgcolor="'.$rowColor.'">'."\n"; } if (@parts > 1) { $$triggered{$symb}{text} .= ' - <td align="right"><small>part - '.$_.'<small></td>'; + <td align="right"><small>part - '.$part.'<small></td>'; } else { $$triggered{$symb}{text} .= ' <td align="right"><small>single part</small></td>'; } $$triggered{$symb}{text} .= ' - <td align="right"><small>'.$stats{$_}{users}.'</small></td> - <td align="right"><small>'.$stats{$_}{attempts}.'</small></td> - <td align="right"><small>'.$stats{$_}{degdiff}.'</small></td> + <td align="right"><small>'.$stats{$part}{users}.'</small></td> + <td align="right"><small>'.$stats{$part}{attempts}.'</small></td> + <td align="right"><small>'.$stats{$part}{degdiff}.'</small></td> + <td align="right"><small>'.$lastreset{$part}.'</small></td> + <td align="right"><small><input type="checkbox" name="'.$resetname.'" /><input type="hidden" name="'.$resettitle.'" value="'.&Apache::lonnet::escape($$triggered{$symb}{title}).'" /></td> </tr>'; $$triggered{$symb}{numparts} ++; } @@ -587,6 +685,86 @@ sub getitems { } } +sub get_curr_thresholds { + my ($threshold,$cdom,$crs) = @_; + my %coursesettings = &Apache::lonnet::dump('environment', + $cdom,$crs,'internal.threshold'); + if (exists($coursesettings{'internal.threshold_av_attempts'})) { + $$threshold{'av_attempts'} = $coursesettings{'internal.threshold_av_attempts'}; + } + if (exists($coursesettings{'internal.threshold_degdiff'})) { + $$threshold{'degdiff'} = $coursesettings{'internal.threshold_degdiff'}; + } + if (exists($coursesettings{'internal.threshold_numstudents'})) { + $$threshold{'numstudents'} = $coursesettings{'internal.threshold_numstudents'}; + } +} + +sub process_reset { + my ($dom,$crs) = @_; + my $result = '<b>Counters reset for following problems (and parts):</b><br />'; + my @agg_types = ('attempts','users','correct'); + my %agg_titles = ( + attempts => 'Number of submissions', + users => 'Students with submissions', + correct => 'Number of correct submissions', + ); + my @resets = (); + my %titles = (); + foreach my $key (keys(%env)) { + next if ($key !~ /^form\.reset_(.+)$/); + my $title = &Apache::lonnet::unescape($env{'form.title_'.$1}); + my $reset_item = &Apache::lonnet::unescape($1); + my %curr_aggregates = &Apache::lonnet::dump('nohist_resourcetracker',$dom,$crs,$reset_item); + my %aggregates = (); + my ($symb,$part) = split(/\0/,$reset_item); + foreach my $type (@agg_types) { + $aggregates{$reset_item."\0".$type} = 0; + } + $aggregates{$reset_item."\0".'resettime'} = time; + my $putresult = &Apache::lonnet::put('nohist_resourcetracker',\%aggregates, + $dom,$crs); + if ($putresult eq 'ok') { + $result .= $title.' -part '.$part.': '; + my %new_aggregates = &Apache::lonnet::dump('nohist_resourcetracker',$dom,$crs,$reset_item); + foreach my $type (@agg_types) { + $result .= $agg_titles{$type}.' = '.$new_aggregates{$reset_item."\0".$type}.'; '; + } + $result =~ s/; $//; + $result .= '<br />'; + } else { + $result = $title.' -part '.$part.': '.&mt('Unable to reset counters to zero due to [_1]',$putresult).'.<br />'."\n"; + } + } + return $result; +} + +sub process_update { + my ($dom,$crs,$threshold_titles) = @_; + my $setoutput = '<b>Changes to threshold(s) for problem tracking:</b><br />'; + foreach (keys %env) { + next if ($_!~/^form\.(.+)\_setparmval$/); + my $name = $1; + my $value = $env{'form.'.$name.'_value'}; + if ($name && defined($value)) { + my $put_result = &Apache::lonnet::put('environment', + {$name=>$value},$dom,$crs); + + my ($shortname) = ($name =~ /^internal\.threshold_(.+)$/); + if ($put_result eq 'ok') { + $setoutput.=&mt('Set threshold for [_1] to [_2]', + '<b>'.$$threshold_titles{$shortname}.'</b>', + '<b>'.$value.'</b>').'<br />'; + } else { + $setoutput.=&mt('Unable to set threshold for [_1] to [_2] due to [_3].', + '<b>'.$name.'</b>','<b>'.$value.'</b>', + '<tt>'.$put_result.'</tt>').'<br />'; + } + } + } + return $setoutput; +} + sub getmail { my ($newmsgs,$critmsgs) = @_; # Check for unread mail in course @@ -649,7 +827,8 @@ sub getmail { } sub cmp_title { - my ($atitle,$btitle) = (lc($_[0]->compTitle),lc($_[1]->compTitle)); + my ($a,$b,$res_title) = @_; + my ($atitle,$btitle) = (lc($$res_title{$a}),lc($$res_title{$b})); $atitle=~s/^\s*//; $btitle=~s/^\s*//; return $atitle cmp $btitle;