+
+
+
+
+
+
+
+
+ Threshold Name
+ Current value
+ Change?
+ ');
+ 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('
+
+ '.$threshold_titles{$type}.'
+ '.&Apache::lonhtmlcommon::textbox($parameter.'_value',
+ $threshold{$type},
+ 10,$onchange).'
+ '
+ .&Apache::lonhtmlcommon::checkbox($parameter.'_setparmval').
+ '
+ ');
+ $rowNum ++;
+ }
+ $r->print('
+
+
+ ');
+}
+
sub getitems {
- my ($unread,$ungraded,$bombed,$newdiscussions,$tograde,$bombs) = @_;
+ 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');
+ 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',
+ $cdom,$crs);
+ my $warningnum = 0;
foreach my $key (keys(%lastread)) {
my $newkey = $key;
$newkey =~ s/_lastread$//;
@@ -426,19 +524,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();
- my $ressymb = $symb;
- if ($ressymb =~ m-(___adm/\w+/\w+)/(\d+)/bulletinboard$-) {
- $ressymb = 'bulletin___'.$2.$1.'/'.$2.'/bulletinboard';
- unless ($ressymb =~ m|bulletin___\d+___adm/wrapper|) {
- $ressymb=~s|(bulletin___\d+___)|$1adm/wrapper/|;
- }
- }
-
+ $$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;
@@ -448,41 +542,47 @@ 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\./)) {
if ($prevread <$contrib{$id.':timestamp'}) {
$$unread{$ressymb}{$unreadcount} = $id.': '.$contrib{$id.':subject'};
$unreadcount ++;
- push(@{$newdiscussions}, $ressymb);
}
}
}
}
- }
+ if ($unreadcount) { push(@{$newdiscussions}, $ressymb); }
+ }
# Check for ungraded problems
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);
+ my ($partlist,$handgrade,$responseType) =
+ &Apache::grades::response_type($url,$symb);
+ my $handgradeable;
+ foreach my $value (values(%{$handgrade})) {
+ if ($value eq 'yes') { $handgradeable=1; last; }
+ }
+ next 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 $graded = 0;
+ my $ungraded = 0;
foreach (keys(%status)) {
$submitted = 1 if ($status{$_} ne 'nothing');
- $graded = 1 if ($status{$_} !~ /^correct/);
+ $ungraded = 1 if ($status{$_} =~ /^ungraded/);
my ($foo,$partid,$foo1) = split(/\./,$_);
if ($status{'resource.'.$partid.'.submitted_by'} ne '') {
$submitted = 0;
}
}
- next if (!$submitted || !$graded);
+ next if (!$submitted || !$ungraded);
$ctr ++;
}
if ($ctr) {
@@ -495,16 +595,165 @@ sub getitems {
# Check for bombs
if ($resource->getErrors()) {
my $errors = $resource->getErrors();
+ $errors =~ s/^,//;
my @bombs = split(/,/, $errors);
my $errorcount = scalar(@bombs);
my $errorlink = '';
+ &Apache::lonnet::escape($bombs[0]).'">'.
+ $title.' ';
$$bombed{$symb}{errorcount} = $errorcount;
$$bombed{$symb}{errorlink} = $errorlink;
push(@{$bombs}, $symb);
}
+# 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) {
+ %{$stats{$part}} = ();
+ my ($attempts,$users,$corrects,$degdiff,$av_attempts);
+ if (exists($resourcetracker{$symb."\0".$part."\0attempts"})) {
+ $attempts = $resourcetracker{$symb."\0".$part."\0attempts"};
+ }
+ if (exists($resourcetracker{$symb."\0".$part."\0users"})) {
+ $users = $resourcetracker{$symb."\0".$part."\0users"};
+ }
+ if (exists($resourcetracker{$symb."\0".$part."\0correct"})) {
+ $corrects = $resourcetracker{$symb."\0".$part."\0correct"};
+ }
+ if ($attempts > 0) {
+ $degdiff = 1 - ($corrects/$attempts);
+ $degdiff = sprintf("%.2f",$degdiff);
+ }
+ if ($users > 0) {
+ $av_attempts = $attempts/$users;
+ $av_attempts = sprintf("%.2f",$av_attempts);
+ }
+ 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;
+ }
+ }
+ if ($warning) {
+ if ($warningnum %2 == 1) {
+ $rowColor = $rowColor1;
+ } else {
+ $rowColor = $rowColor2;
+ }
+ $$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} .= '