[LON-CAPA-cvs] cvs: loncom /interface lonwhatsnew.pm
raeburn
lon-capa-cvs@mail.lon-capa.org
Mon, 23 May 2005 23:06:28 -0000
This is a MIME encoded message
--raeburn1116889588
Content-Type: text/plain
raeburn Mon May 23 19:06:28 2005 EDT
Modified files:
/loncom/interface lonwhatsnew.pm
Log:
Fixes to display of problems with errors. Ability to set a threshold for av attempts, deg diff, number of submissions. Ability to reset aggregate counters for tries, degdiff, users on a part-by-part basis.
--raeburn1116889588
Content-Type: text/plain
Content-Disposition: attachment; filename="raeburn-20050523190628.txt"
Index: loncom/interface/lonwhatsnew.pm
diff -u loncom/interface/lonwhatsnew.pm:1.12 loncom/interface/lonwhatsnew.pm:1.13
--- loncom/interface/lonwhatsnew.pm:1.12 Fri Apr 29 10:54:18 2005
+++ loncom/interface/lonwhatsnew.pm Mon May 23 19:06:23 2005
@@ -1,5 +1,5 @@
#
-# $Id: lonwhatsnew.pm,v 1.12 2005/04/29 14:54:18 raeburn Exp $
+# $Id: lonwhatsnew.pm,v 1.13 2005/05/23 23:06:23 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -52,10 +52,13 @@
}
&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,15 +71,15 @@
}
&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'));
@@ -94,30 +97,17 @@
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',
+ );
+ if ($command eq 'chgthreshold') {
+ &display_config_box($r,$command,$tabbg,\%threshold_titles);
} else {
- &display_actions_box($r,$picker);
+ &display_actions_box($r,$command,\%threshold_titles);
}
$r->print(<<END_OF_BLOCK);
</td>
@@ -155,7 +145,7 @@
#-------------------------------
sub display_actions_box() {
- my ($r,$picker) = @_;
+ my ($r,$command,$threshold_titles) = @_;
my $rowColor1 = "#ffffff";
my $rowColor2 = "#eeeeee";
@@ -181,18 +171,38 @@
$function='admin';
}
+ my %threshold = (
+ av_attempts => 0,
+ degdiff => 0.01,
+ numstudents => 0,
+ );
+
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 />');
return;
}
- $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 $result;
+ my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
+
+ 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%" />');
+ }
+
+ &get_curr_thresholds(\%threshold,$cdom,$crs);
+ &getitems(\%unread,\%ungraded,\%bombed,\%triggered,\@newdiscussions,\@tograde,\@bombs,\@warnings,$rowColor1,$rowColor2,\%threshold,$cdom,$crs);
+ my ($msgcount,$critmsgcount) = &getmail(\@newmsgs,\@critmsgs);
+
+ $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,6 +252,7 @@
END
my $bombnum = 0;
if (@bombs > 0) {
+ $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) } @bombs;
foreach my $bomb (@bombs) {
if ($bombnum %2 == 1) {
@@ -249,7 +260,7 @@
} 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 +269,30 @@
$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">
END
- my $warningnum = 0;
- if (@warnings > 0) {
+ 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>');
+ $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 +306,9 @@
$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 />');
@@ -414,33 +431,82 @@
#-------------------------------
# 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) = @_;
+ 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);
+
+ $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) = @_;
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');
+ 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 %res_title;
my $warningnum = 0;
foreach my $key (keys(%lastread)) {
my $newkey = $key;
@@ -451,11 +517,12 @@
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})) {
@@ -468,9 +535,8 @@
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\./)) {
@@ -515,10 +581,12 @@
# 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);
@@ -526,6 +594,7 @@
# Compile maxtries and degree of difficulty for problem parts
my @parts = @{$resource->parts()};
my %stats;
+ my %lastreset = ();
my $warning = 0;
my $rowColor;
foreach my $part (@parts) {
@@ -547,10 +616,12 @@
if ($users > 0) {
$av_attempts = $attempts/$users;
}
- if (($degdiff ne '' && $degdiff >= $diffcheck) || ($av_attempts ne '' && $av_attempts >= $triescheck)) {
+ 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;
+ my %resethash = &Apache::lonnet::restore($symb,'nohist_resourcetracker',$cdom,$crs);
+ $lastreset{$part} = &get_counter_resets(\%resethash,$part);
$warning = 1;
}
}
@@ -563,6 +634,8 @@
$$triggered{$symb}{title} = $resource->title;
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";
}
@@ -577,6 +650,8 @@
<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 +662,101 @@
}
}
+sub get_counter_resets {
+ my ($resethash,$part) = @_;
+ my $lastreset = 'None';
+ if ($$resethash{'version'}) {
+ for (my $version=1;$version<=$$resethash{'version'};$version++) {
+ if (exists($$resethash{$version.':'.$part.'prev_attempts'})) {
+ $lastreset = $$resethash{$version.':timestamp'};
+ }
+ }
+ }
+ unless ($lastreset eq 'None') {
+ $lastreset = localtime($lastreset);
+ }
+ return $lastreset;
+}
+
+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 %resethash = ();
+ my %aggregates = ();
+ my ($symb,$part) = split/\0/,$reset_item;
+ foreach my $type (@agg_types) {
+ $aggregates{$reset_item."\0".$type} = 0;
+ $resethash{$part."\0".'prev_'.$type} = $curr_aggregates{$reset_item."\0".$type};
+ }
+ my $putresult = &Apache::lonnet::put('nohist_resourcetracker',\%aggregates,
+ $dom,$crs);
+ if ($putresult eq 'ok') {
+ my $storeresult = &Apache::lonnet::cstore(\%resethash,$symb,'nohist_resourcetracker',$dom,$crs);
+ $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 ').$putresult.'.<br />'."\n";
+ }
+ }
+ return $result;
+}
+
+sub process_update {
+ my ($dom,$crs,$threshold_titles) = @_;
+ my $setoutput = '<b>Changes to threshold(s):</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').' <b>'.$$threshold_titles{$shortname}.'</b> '.&mt('to').' <b>'.$value.'</b>.<br />';
+ } else {
+ $setoutput.=&mt('Unable to set threshold for').' <b>'.$name.'</b> '.&mt('to').
+ ' <b>'.$value.'</b> '.&mt('due to').' '.$put_result.'.<br />';
+ }
+ }
+ }
+ return $setoutput;
+}
+
sub getmail {
my ($newmsgs,$critmsgs) = @_;
# Check for unread mail in course
--raeburn1116889588--