# The LearningOnline Network with CAPA # Handler for requesting to have slots added to a students record # # $Id: slotrequest.pm,v 1.4 2005/06/04 08:17:06 albertel 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/ # ### package Apache::slotrequest; use strict; use Apache::Constants qw(:common :http :methods); use Apache::loncommon(); use Apache::lonlocal; use Apache::lonnet; sub fail { my ($r,$code)=@_; if ($code eq 'not_valid') { $r->print('

'.&mt('Unable to understand what resource you wanted to sign up for.').'

'.$env{'form.symb'}); } $r->print('

'. &mt('Return to last resource').'

'); &end_page($r); } sub start_page { my ($r)=@_; my $html=&Apache::lonxml::xmlbegin(); $r->print($html.''. &mt('Request another Worktime').''); $r->print(&Apache::loncommon::bodytag('Requesting another Worktime')); } sub end_page { my ($r)=@_; $r->print(&Apache::loncommon::endbodytag().''); } =pod slot_reservations db - keys are - slotname\0id -> value is an hashref of name -> user@domain of holder timestamp -> timestamp of reservation symb -> symb of resource that it is reserved for =cut sub get_course { (undef,my $courseid)=&Apache::lonxml::whichuser(); my $cdom=$env{'course.'.$courseid.'.domain'}; my $cnum=$env{'course.'.$courseid.'.num'}; return ($cnum,$cdom); } sub get_reservation_ids { my ($slot_name)=@_; my ($cnum,$cdom)=&get_course(); my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum, "^$slot_name\0"); my ($tmp)=%consumed; if ($tmp=~/^error: 2 / ) { return 0; } return keys(%consumed); } sub space_available { my ($slot_name,$slot)=@_; my $max=$slot->{'maxspace'}; if (!defined($max)) { return 1; } my $consumed=scalar(&get_reservation_ids($slot_name)); if ($consumed < $max) { return 1 } return 0; } sub check_for_reservation { my ($symb)=@_; my $student = &Apache::lonnet::EXT("resource.0.availablestudent", $symb, $env{'user.domain'}, $env{'user.name'}); my $course = &Apache::lonnet::EXT("resource.0.available", $symb, $env{'user.domain'}, $env{'user.name'}); my @slots = (split(/:/,$student), split(/:/, $course)); &Apache::lonxml::debug(" slot list is ".join(':',@slots)); my ($cnum,$cdom)=&get_course(); my %slots=&Apache::lonnet::get('slots', [@slots], $cdom, $cnum); foreach my $slot_name (@slots) { next if (!defined($slots{$slot_name}) || !ref($slots{$slot_name})); &Apache::lonxml::debug(time." $slot_name ". $slots{$slot_name}->{'starttime'}." -- ". $slots{$slot_name}->{'startreserve'}); if ($slots{$slot_name}->{'starttime'} > time && $slots{$slot_name}->{'startreserve'} < time) { # between start of reservation times and start of slot return($slot_name, $slots{$slot_name}); } } return (undef,undef); } # FIXME - depends on the parameter for the resource to be correct # tho prevent multiple reservations sub make_reservation { my ($slot_name,$slot,$symb)=@_; my ($cnum,$cdom)=&get_course(); my $value=&Apache::lonnet::EXT("resource.0.availablestudent",$symb, $env{'user.domain'},$env{'user.name'}); &Apache::lonxml::debug("value is $value
"); foreach my $other_slot (split(/:/, $value)) { if ($other_slot eq $slot_name) { my %consumed=&Apache::lonnet::dump('slot_reservations', $cdom, $cnum, "^$slot_name\0"); my $me=$env{'user.name'}.'@'.$env{'user.domain'}; foreach my $key (keys(%consumed)) { if ($consumed{$key}->{'name'} eq $me) { my $num=(split('\0',$key))[1]; return -$num; } } } } my $max=$slot->{'maxspace'}; if (!defined($max)) { $max=99999; } my (@ids)=&get_reservation_ids($slot_name); # FIXME we could end up having holes... my $last=0; foreach my $id (@ids) { my $num=(split('\0',$id))[1]; if ($num > $last) { $last=$num; } } my $wanted=$last+1; &Apache::lonxml::debug("wanted $wanted
"); if ($wanted >= $max) { # full up return -1; } my %reservation=('name' => $env{'user.name'}.'@'.$env{'user.domain'}, 'timestamp' => time, 'symb' => $symb); my $success=&Apache::lonnet::newput('slot_reservations', {"$slot_name\0$wanted" => \%reservation}, $cdom, $cnum); if ($success eq 'ok') { #FIXME need to set the parm my $new_value=$slot_name; if ($value) { $new_value=$value.':'.$new_value; } my $result=&Apache::lonparmset::storeparm_by_symb($symb, '0_availablestudent', 1, $new_value, 'string', $env{'user.name'}, $env{'user.domain'}); &Apache::lonxml::debug("hrrm $result"); return $wanted; } # someone else got it return undef; } sub get_slot { my ($r,$symb)=@_; my %slot=&Apache::lonnet::get_slot($env{'form.slotname'}); my $reserved=&make_reservation($env{'form.slotname'}, \%slot,$symb); my $description=&get_description($env{'form.slotname'},\%slot); if ($reserved > -1) { $r->print("

Success: $description

"); $r->print('

'. &mt('Return to last resource').'

'); return; } elsif ($reserved < 0) { $r->print("

Already reserved: $description

"); $r->print('

'. &mt('Return to last resource').'

'); return; } my %lt=('request'=>"Request another attempt", 'try' =>'Try again'); %lt=&Apache::lonlocal::texthash(%lt); $r->print(< Failed to reserve a spot for $description.

?

or

or STUFF $r->print('

'. &mt('Return to last resource').'

'); return; } sub allowed_slot { my ($slot_name,$slot,$symb)=@_; #already started if ($slot->{'starttime'} < time) { return 0; } #already ended if ($slot->{'endtime'} < time) { return 0; } # not allowed to pick this one if (defined($slot->{'type'}) && $slot->{'type'} ne 'schedulable_student') { return 0; } # not allowed for this resource if (defined($slot->{'symb'}) && $slot->{'symb'} ne $symb) { return 0; } return 1; } sub get_description { my ($slot_name,$slot)=@_; my $description=$slot->{'description'}; if (!defined($description)) { $description=&mt('[_1] From [_2] to [_3]',$slot_name, &Apache::lonlocal::locallocaltime($slot->{'starttime'}), &Apache::lonlocal::locallocaltime($slot->{'endtime'})); } return $description; } sub show_choices { my ($r,$symb)=@_; my ($cnum,$cdom)=&get_course(); my %slots=&Apache::lonnet::dump('slots',$cdom,$cnum); my $available; $r->print(''); foreach my $slot (sort { return $slots{$a}->{'starttime'} <=> $slots{$b}->{'starttime'} } (keys(%slots))) { next if (!&allowed_slot($slot,$slots{$slot})); $available++; my $description=&get_description($slot,$slots{$slot}); my $form=&mt('Unavailable'); if (&space_available($slot,$slots{$slot},$symb)) { my $escsymb=&Apache::lonnet::escape($symb); $form=< STUFF } $r->print(< STUFF } if (!$available) { $r->print(''); } $r->print('
$form $description
No avaliable times. '. &mt('Return to last resource').'
'); } sub handler { my $r=shift; &start_page($r); my $symb=&Apache::lonnet::unescape($env{'form.symb'}); my (undef,undef,$res)=&Apache::lonnet::decode_symb($symb); if ($res !~ /\.task$/) { &fail($r,'not_valid'); return OK; } if ($env{'form.requestattempt'}) { &show_choices($r,$symb); } elsif ($env{'form.command'} eq 'get') { &get_slot($r,$symb); } &end_page($r); return OK; } 1; __END__