# The LearningOnline Network with CAPA # Display first access times for timed (interval) items for active # students in a course. # # $Id: lonaccesstimes.pm,v 1.2 2017/01/31 18:55:03 raeburn 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/ # ############################################################## ############################################################## =pod =head1 NAME lonaccesstimes - Handler to display first access times for timed (interval) items. =head1 SYNOPSIS lonaccess times provides an interface for displaying first access times for timed (interval) items for active students in a course. =head1 DESCRIPTION This module is used to display first access times for items in a course set when a student pushes "Show Resource" to begin a timed (interval) quiz. =head1 OVERVIEW Users with the vgr privilege in a course can use /adm/accesstimes to view first access times set by users with unexpired student roles in a course, for all resources or maps for which the interval parameter is set. The first access is stored when a student pushed the "Show Resource" button to start the timer to gain access to a timed quiz or exam. Users with the mgr privilege can use the "Reset Student Access Times" helper to reset access times, in case of network trouble having prevented a student from completing a timed quiz/exam. This module is provided for use by helpdesk staff who may receive the vgr privilege in a course, but not the mgr privilege, so they can advise students or faculty who contact the helpdesk on what to do if access to a timed quiz needs to be provided to a student after the clock has run out. =head1 INTERNAL SUBROUTINES =over =item &print_selectors() Prints page used to select a single item using the interval parameter, and one or more enrolled students/members for whom first access times are to be displayed for that item (specific resource, map, or course-wide). Inputs: 2 $r - Request object. $crstype - Course type (either Course or Community). Outputs: none Side Effects: prints web page containing items for which timed (interval) parameters have been set (use radio buttons to select one), and also a table of users with active student roles, with checkboxes to select users. =item &print_results() Prints first access times found for specified item (resource, map or course) and specified students. Inputs: 2 $r - Request object. $crstype - Course type (either Course or Community). Outputs: none Side Effects: prints web page containing first access times. =back =cut package Apache::lonaccesstimes; use strict; use Apache::lonnet; use Apache::Constants qw(:common :http); use Apache::loncommon(); use Apache::lonblockingmenu(); use Apache::lonselstudent(); use Apache::lonlocal; use lib '/home/httpd/lib/perl/'; use LONCAPA qw(:DEFAULT :match); sub handler { my $r = shift; &Apache::loncommon::content_type($r,'text/html'); $r->send_http_header; return OK if $r->header_only; # Needs to be in a course if (! ($env{'request.course.fn'})) { # Not in a course $env{'user.error.msg'}= "/adm/accesstimes:vgr:0:0:Cannot view first access times for timed items in a course"; return HTTP_NOT_ACCEPTABLE; } # ----------------------------------------------------------- Permissions check unless ((&Apache::lonnet::allowed('vgr',$env{'request.course.id'})) || (&Apache::lonnet::allowed('vgr',$env{'request.course.id'}. '/'.$env{'request.course.sec'}))) { $env{'user.error.msg'}= "/adm/setblock:vgr:0:0:Cannot view first access times for timed items in a course"; return HTTP_NOT_ACCEPTABLE; } # ------------------------------------------------------------------ Breadcrumbs &Apache::lonhtmlcommon::clear_breadcrumbs(); &Apache::lonhtmlcommon::add_breadcrumb ({href=>'/adm/parmset', text=>'Content and Problem Settings'}); &Apache::lonhtmlcommon::add_breadcrumb ({href=>'/adm/accesstimes', text=>'First Access times for timed quizzes/exams'}); my $phase = $env{'form.phase'}; my $crstype = &Apache::loncommon::course_type(); # ------------------------------------------------------- Show first access times if ($phase eq 'display') { &Apache::lonhtmlcommon::add_breadcrumb ({href=>'/adm/accesstimes', text=>'Results'}); $r->print( &Apache::loncommon::start_page('Display first access times'). &Apache::lonhtmlcommon::breadcrumbs('First access times')); &print_results($r,$crstype); } else { my $js = &Apache::lonblockingmenu::details_javascript(); $r->print( &Apache::loncommon::start_page('Filters for first access times',$js). &Apache::lonhtmlcommon::breadcrumbs('First access times')); &print_selectors($r,$crstype); } $r->print(&Apache::loncommon::end_page()); return OK; } sub print_selectors { my ($r,$crstype) = @_; # ------------------------------------------------------ Retrieve active students my ($course_personnel, $current_members, $expired_members, $future_members) = &Apache::lonselstudent::get_people_in_class($env{'request.course.sec'}); # ---------------------------------------------------- Get Time Limit parameters my %intervals = &Apache::lonblockingmenu::get_timed_items(); # ------------------------------------------------------------- Display selectors $r->print('
'); if ((ref($current_members) eq 'ARRAY') && (@{$current_members} > 0) && (keys(%intervals) > 0)) { my %titles = &Apache::lonlocal::texthash( 'intervals' => 'Select timed interval setting (for course, folder or resource)', 'active' => 'Select from currently enrolled students', ); if ($crstype eq 'Community') { $titles{'active'} = &mt('Select from current community members'); } if ($env{'request.course.sec'}) { $titles{'active'} = &mt('Select from currently enrolled students in section: [_1]', $env{'request.course.sec'}); if ($crstype eq 'Community') { $titles{'active'} = &mt('Select from current community members in section: [_1]', $env{'request.course.sec'}); } } my $navmap = Apache::lonnavmaps::navmap->new(); if (!ref($navmap)) { $r->print('

'.&mt('Failed to retrieve course contents').'

'); } else { my $parmcount = 0; $r->print('

'.$titles{'intervals'}.'

'. &Apache::lonblockingmenu::create_interval_form(\%intervals,$parmcount,$navmap,'accesstimes'). '
'); my %default; $r->print( '

'.$titles{'active'}.'

'. &Apache::lonselstudent::render_student_list( $current_members, 'accessform', 'current', \%default,1,'firstaccess',1, 'accesstimes')); } $r->print(''. ''); } else { if ((ref($current_members) eq 'ARRAY') && (@{$current_members} == 0)) { if ($env{'request.course.sec'}) { if ($crstype eq 'Community') { $r->print('

'.&mt('No current community members in section [_1]', $env{'request.course.sec'}).'

'); } else { $r->print('

'.&mt('No students currently enrolled in section [_1]', $env{'request.course.sec'}).'

'); } } else { if ($crstype eq 'Community') { $r->print('

'.&mt('No current community members').'

'); } else { $r->print('

'.&mt('No students currently enrolled').'

'); } } } if (keys(%intervals) == 0) { $r->print('

'.&mt('No timed interval settings currently apply to course, folder(s) or resource(s)').'

'); } } $r->print('
'); } sub print_results { my ($r,$crstype) = @_; my $usertype = &Apache::lonnet::plaintext('st',$crstype); my $item = $env{'form.firstaccess_0'}; my $title; if ($item ne '') { my $symb; if ($item =~ /\.(sequence|page)$/) { if (&Apache::lonnet::is_on_map($item)) { my $navmap = Apache::lonnavmaps::navmap->new(); if (ref($navmap)) { my $mapres = $navmap->getResourceByUrl($item); if (ref($mapres)) { $symb = $mapres->symb(); $title = $mapres->compTitle(); } else { $title = &Apache::lonnet::gettitle($item); } my ($path,$hierarchy); $hierarchy = &Apache::lonblockingmenu::show_timer_path('map',$item,$navmap); if ($hierarchy) { $path = ' '. &mt('(in: [_1])',$hierarchy). ''; } $title = &mt('Timer for all items in folder: [_1]', ''.$title.'').$path; } else { $r->print('

'.&mt('Could not find time interval setting for selected item').'

'); } } else { $r->print('

'.&mt('Could not find time interval setting for selected item').'

'); } } elsif ($item eq 'course') { $symb = $item; $title = &mt('Timer for all items in course'); } else { my $navmap = Apache::lonnavmaps::navmap->new(); if (ref($navmap)) { my $resobj = $navmap->getBySymb($item); my ($path,$hierarchy); if (ref($resobj)) { $symb = $item; $title = $resobj->compTitle(); } if ($title eq '') { $title = &Apache::lonnet::gettitle($item); } $hierarchy = &Apache::lonblockingmenu::show_timer_path('resource',$item,$navmap); if ($hierarchy) { $path = ' '. &mt('(in: [_1])',$hierarchy). ''; } $title = &mt('Timer for resource: [_1]',''.$title.''). $path; } } if ($symb) { if ($title) { $r->print('

'.$title.'

'); } my @students = &Apache::loncommon::get_env_multiple('form.firstaccess_forminput'); if (@students) { my ($course_personnel, $current_members, $expired_members, $future_members) = &Apache::lonselstudent::get_people_in_class($env{'request.course.sec'}); my %active; if (ref($current_members) eq 'ARRAY') { map { $active{$_->[0]} = 1; } @{$current_members}; } my (@hasaccess,@noaccess); my $key=$env{'request.course.id'}."\0".$symb; foreach my $name (sort(@students)) { my ($uname,$udom,$sec,$fullname)=split(':',$name); next unless ($active{$uname.':'.$udom}); if (!$fullname) { $fullname="$uname:$udom"; } my %times=&Apache::lonnet::get('firstaccesstimes', [$key],$udom,$uname); if (!$times{$key}) { push(@noaccess,[$name,$fullname]); } else { push(@hasaccess,[$name,$fullname,$times{$key}]); } } if ((@hasaccess == 0) && (@noaccess == 0)) { $r->print('

'.&mt('No valid users selected to check for first access times').'

'); } else { if (@hasaccess > 0) { $r->print('

'.&mt("Access times found for [quant,_1,$usertype]",scalar(@hasaccess)).'

'. '

'.&Apache::loncommon::start_data_table(). &Apache::loncommon::start_data_table_header_row(). ''.&mt('User').''.&mt('Fullname').''. ''.&mt('First access time').''. &Apache::loncommon::end_data_table_header_row()); foreach my $item (@hasaccess) { if (ref($item) eq 'ARRAY') { $r->print(&Apache::loncommon::start_data_table_row(). ''.$item->[0].''. ''.$item->[1].''. ''.&Apache::lonlocal::locallocaltime($item->[2]).''. &Apache::loncommon::start_data_table_row()); } } $r->print(&Apache::loncommon::end_data_table().'

'); } if (@noaccess > 0) { $r->print('

'.&mt("No access times found for [quant,_1,$usertype]",scalar(@noaccess)).'

'. '

'.&Apache::loncommon::start_data_table(). &Apache::loncommon::start_data_table_header_row(). ''.&mt('User').''.&mt('Fullname').''. &Apache::loncommon::end_data_table_header_row()); foreach my $item (@noaccess) { if (ref($item) eq 'ARRAY') { $r->print(&Apache::loncommon::start_data_table_row(). ''.$item->[0].''. ''.$item->[1].''. &Apache::loncommon::start_data_table_row()); } } $r->print(&Apache::loncommon::end_data_table().'

'); } } } else { if ($crstype eq 'Community') { $r->print('

'.&mt('No members selected to check for first access times').'

'); } else { $r->print('

'.&mt('No students selected to check for first access times').'

'); } } } else { $r->print('

'.&mt('Could not find time interval setting for selected item').'

'); } } else { $r->print('

'.&mt('No item selected to check for first access times').'

'); } return; } 1; __END__