version 1.1, 2005/05/31 17:42:11
|
version 1.13, 2005/09/09 18:27:56
|
Line 37 use Apache::lonnet;
|
Line 37 use Apache::lonnet;
|
|
|
sub fail { |
sub fail { |
my ($r,$code)=@_; |
my ($r,$code)=@_; |
$r->print(); |
if ($code eq 'not_valid') { |
|
$r->print('<p>'.&mt('Unable to understand what resource you wanted to sign up for.').'</p>'); |
|
|
|
} elsif ($code eq 'not_allowed') { |
|
$r->print('<p>'.&mt('Not allowed to sign up or change reservations at this time.').'</p>'); |
|
} else { |
|
$r->print('<p>'.&mt('Failed.').'</p>'); |
|
} |
|
|
|
$r->print('<p><a href="/adm/flip?postdata=return:">'. |
|
&mt('Return to last resource').'</a></p>'); |
&end_page($r); |
&end_page($r); |
} |
} |
|
|
Line 54 sub end_page {
|
Line 64 sub end_page {
|
$r->print(&Apache::loncommon::endbodytag().'</html>'); |
$r->print(&Apache::loncommon::endbodytag().'</html>'); |
} |
} |
|
|
|
=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}->{'endtime'} > time && |
|
$slots{$slot_name}->{'startreserve'} < time) { |
|
# between start of reservation times and end of slot |
|
return($slot_name, $slots{$slot_name}); |
|
} |
|
} |
|
return (undef,undef); |
|
} |
|
|
|
sub check_for_conflict { |
|
my ($symb,$new_slot_name)=@_; |
|
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)); |
|
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})); |
|
|
|
next if (!defined($slots{$slot_name}->{'uniqueperiod'}) || |
|
!ref($slots{$slot_name}->{'uniqueperiod'})); |
|
my ($start,$end)=@{$slots{$slot_name}->{'uniqueperiod'}}; |
|
if ($start<time && time < $end) { |
|
return $slot_name; |
|
} |
|
} |
|
return undef; |
|
|
|
} |
|
|
|
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<br />"); |
|
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); |
|
|
|
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<br />"); |
|
if (scalar(@ids) >= $max) { |
|
# full up |
|
return undef; |
|
} |
|
|
|
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') { |
|
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 release_slot { |
|
my ($r,$symb,$slot_name,$inhibit_return_link)=@_; |
|
|
|
if ($slot_name eq '') { $slot_name=$env{'form.slotname'}; } |
|
my ($cnum,$cdom)=&get_course(); |
|
|
|
# get parameter string, check for existance, rebuild string with the slot |
|
|
|
my @slots = split(/:/,&Apache::lonnet::EXT("resource.0.availablestudent", |
|
$symb,$env{'user.domain'}, |
|
$env{'user.name'})); |
|
my @new_slots; |
|
foreach my $exist_slot (@slots) { |
|
if ($exist_slot eq $slot_name) { next; } |
|
push(@new_slots,$exist_slot); |
|
} |
|
my $new_param = join(':',@new_slots); |
|
|
|
# get slot reservations, check if user has one, if so remove reservation |
|
my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum, |
|
"^$slot_name\0"); |
|
foreach my $entry (keys(%consumed)) { |
|
if ( $consumed{$entry}->{'name'} eq |
|
($env{'user.name'}.'@'.$env{'user.domain'}) ) { |
|
&Apache::lonnet::del('slot_reservations',[$entry], |
|
$cdom,$cnum); |
|
} |
|
} |
|
# store new parameter string |
|
my $result=&Apache::lonparmset::storeparm_by_symb($symb, |
|
'0_availablestudent', |
|
1, $new_param, 'string', |
|
$env{'user.name'}, |
|
$env{'user.domain'}); |
|
my %slot=&Apache::lonnet::get_slot($slot_name); |
|
my $description=&get_description($env{'form.slotname'},\%slot); |
|
$r->print("<p>Released Reservation: $description</p>"); |
|
if (!$inhibit_return_link) { |
|
$r->print('<p><a href="/adm/flip?postdata=return:">'. |
|
&mt('Return to last resource').'</a></p>'); |
|
} |
|
return 1; |
|
} |
|
|
|
sub get_slot { |
|
my ($r,$symb)=@_; |
|
|
|
my $slot_name=&check_for_conflict($symb,$env{'form.slotname'}); |
|
if ($slot_name) { |
|
my %slot=&Apache::lonnet::get_slot($slot_name); |
|
my $description1=&get_description($slot_name,\%slot); |
|
%slot=&Apache::lonnet::get_slot($env{'form.slotname'}); |
|
my $description2=&get_description($env{'form.slotname'},\%slot); |
|
$r->print("<p>Already have a reservation: $description1</p>"); |
|
if ($slot_name ne $env{'form.slotname'}) { |
|
$r->print(<<STUFF); |
|
<form method="POST" action="/adm/slotrequest"> |
|
<input type="hidden" name="symb" value="$env{'form.symb'}" /> |
|
<input type="hidden" name="slotname" value="$env{'form.slotname'}" /> |
|
<input type="hidden" name="releaseslot" value="$slot_name" /> |
|
<input type="hidden" name="command" value="change" /> |
|
STUFF |
|
$r->print("<p>You can either "); |
|
$r->print(<<STUFF); |
|
<input type="submit" name="change" value="Change" /> |
|
STUFF |
|
$r->print(' your reservation from <b>'.$description1.'</b> to <b>'. |
|
$description2. |
|
'</b> <br />or <a href="/adm/flip?postdata=return:">'. |
|
&mt('Return to last resource').'</a></p>'); |
|
$r->print(<<STUFF); |
|
</form> |
|
STUFF |
|
} else { |
|
$r->print('<p><a href="/adm/flip?postdata=return:">'. |
|
&mt('Return to last resource').'</a></p>'); |
|
} |
|
return; |
|
} |
|
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 (defined($reserved)) { |
|
if ($reserved > -1) { |
|
$r->print("<p>Success: $description</p>"); |
|
$r->print('<p><a href="/adm/flip?postdata=return:">'. |
|
&mt('Return to last resource').'</a></p>'); |
|
return; |
|
} elsif ($reserved < 0) { |
|
$r->print("<p>Already reserved: $description</p>"); |
|
$r->print('<p><a href="/adm/flip?postdata=return:">'. |
|
&mt('Return to last resource').'</a></p>'); |
|
return; |
|
} |
|
} |
|
|
|
my %lt=('request'=>"Availibility list", |
|
'try' =>'Try again'); |
|
%lt=&Apache::lonlocal::texthash(%lt); |
|
|
|
$r->print(<<STUFF); |
|
<p> <font color="red">Failed</font> to reserve a spot for $description. </p> |
|
<p> |
|
<form method="POST" action="/adm/slotrequest"> |
|
<input type="submit" name="Try Again" value="$lt{'try'}" /> |
|
<input type="hidden" name="symb" value="$env{'form.symb'}" /> |
|
<input type="hidden" name="slotname" value="$env{'form.slotname'}" /> |
|
<input type="hidden" name="command" value="get" /> |
|
</form> |
|
? |
|
</p> |
|
<p> |
|
or |
|
<form method="POST" action="/adm/slotrequest"> |
|
<input type="hidden" name="symb" value="$env{'form.symb'}" /> |
|
<input type="submit" name="requestattempt" value="$lt{'request'}" /> |
|
</form> |
|
</p> |
|
or |
|
STUFF |
|
$r->print('<p><a href="/adm/flip?postdata=return:">'. |
|
&mt('Return to last resource').'</a></p>'); |
|
return; |
|
} |
|
|
|
sub allowed_slot { |
|
my ($slot_name,$slot,$symb)=@_; |
|
#already started |
|
if ($slot->{'starttime'} < time) { |
|
# all open slot to be schedulable |
|
#return 0; |
|
} |
|
&Apache::lonxml::debug("$slot_name starttime good"); |
|
#already ended |
|
if ($slot->{'endtime'} < time) { |
|
return 0; |
|
} |
|
&Apache::lonxml::debug("$slot_name endtime good"); |
|
# not allowed to pick this one |
|
if (defined($slot->{'type'}) |
|
&& $slot->{'type'} ne 'schedulable_student') { |
|
return 0; |
|
} |
|
&Apache::lonxml::debug("$slot_name type good"); |
|
# not allowed for this resource |
|
if (defined($slot->{'symb'}) |
|
&& $slot->{'symb'} ne $symb) { |
|
return 0; |
|
} |
|
&Apache::lonxml::debug("$slot_name symb good"); |
|
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('<table border="1">'); |
|
&Apache::lonxml::debug("Checking Slots"); |
|
my ($got_slot)=&check_for_reservation($symb); |
|
foreach my $slot (sort |
|
{ return $slots{$a}->{'starttime'} <=> $slots{$b}->{'starttime'} } |
|
(keys(%slots))) { |
|
|
|
&Apache::lonxml::debug("Checking Slot $slot"); |
|
next if (!&allowed_slot($slot,$slots{$slot})); |
|
|
|
$available++; |
|
|
|
my $description=&get_description($slot,$slots{$slot}); |
|
|
|
my $form=&mt('Unavailable'); |
|
if (($slot eq $got_slot) || |
|
&space_available($slot,$slots{$slot},$symb)) { |
|
my $text=&mt('Select'); |
|
my $command='get'; |
|
if ($slot eq $got_slot) { |
|
$text=&mt('Free Reservation'); |
|
$command='release'; |
|
} |
|
my $escsymb=&Apache::lonnet::escape($symb); |
|
$form=<<STUFF; |
|
<form method="POST" action="/adm/slotrequest"> |
|
<input type="submit" name="Select" value="$text" /> |
|
<input type="hidden" name="symb" value="$escsymb" /> |
|
<input type="hidden" name="slotname" value="$slot" /> |
|
<input type="hidden" name="command" value="$command" /> |
|
</form> |
|
STUFF |
|
} |
|
$r->print(<<STUFF); |
|
<tr> |
|
<td>$form</td> |
|
<td>$description</td> |
|
</tr> |
|
STUFF |
|
} |
|
|
|
if (!$available) { |
|
$r->print('<tr><td>No available times. <a href="/adm/flip?postdata=return:">'. |
|
&mt('Return to last resource').'</a></td></tr>'); |
|
} |
|
$r->print('</table>'); |
|
} |
|
|
|
sub show_table { |
|
my ($r,$symb)=@_; |
|
|
|
my ($cnum,$cdom)=&get_course(); |
|
my %slots=&Apache::lonnet::dump('slots',$cdom,$cnum); |
|
my $available; |
|
$r->print('<table border="1"> |
|
<tr> |
|
<th>Slot name</th> |
|
<th>Type</th> |
|
<th>Description</th> |
|
<th>Start Time</th> |
|
<th>End Time</th> |
|
<th>Max space</th> |
|
<th>Scheduled Students</th> |
|
<th>Proctors</th> |
|
<th>Unique Period</th> |
|
</tr>'); |
|
foreach my $slot (sort |
|
{ return $slots{$a}->{'starttime'} <=> $slots{$b}->{'starttime'} } |
|
(keys(%slots))) { |
|
if (defined($slots{$slot}->{'type'}) |
|
&& $slots{$slot}->{'type'} ne 'schedulable_student') { |
|
#next; |
|
} |
|
my $description=&get_description($slot,$slots{$slot}); |
|
my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum, |
|
"^$slot\0"); |
|
my $ids; |
|
foreach my $entry (sort(keys(%consumed))) { |
|
my (undef,$id)=split("\0",$entry); |
|
$ids.= $id.'-> '.$consumed{$entry}->{'name'}.'<br />'; |
|
} |
|
my $start=localtime($slots{$slot}->{'starttime'}); |
|
my $end=localtime($slots{$slot}->{'endtime'}); |
|
$r->print(<<STUFF); |
|
<tr> |
|
<td>$slot</td> |
|
<td>$slots{$slot}->{'type'}</td> |
|
<td>$description</td> |
|
<td>$start</td> |
|
<td>$end</td> |
|
<td>$slots{$slot}->{'maxspace'}</td> |
|
<td>$ids</td> |
|
<td>$slots{$slot}->{'proctor'}</td> |
|
<td>$slots{$slot}->{'uniqueperiod'}</td> |
|
</tr> |
|
STUFF |
|
} |
|
$r->print('</table>'); |
|
} |
|
|
sub handler { |
sub handler { |
my $r=shift; |
my $r=shift; |
|
|
|
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}); |
&start_page($r); |
&start_page($r); |
my $symb=$env{'form.symb'}; |
my $symb=&Apache::lonnet::unescape($env{'form.symb'}); |
my (undef,undef,$res)=&Apache::lonnet::decode_symb($symb); |
my (undef,undef,$res)=&Apache::lonnet::decode_symb($symb); |
if ($symb !~ /\.task$/) { |
if ($res !~ /\.task$/) { |
&fail($r,'not_valid'); |
&fail($r,'not_valid'); |
return OK; |
return OK; |
} |
} |
|
$env{'request.symb'}=$symb; |
|
my $vgr=&Apache::lonnet::allowed('vgr',$env{'request.course.id'}); |
|
if ($env{'form.command'} eq 'showslots' && $vgr eq 'F') { |
|
&show_table($r,$symb); |
|
} else { |
|
my ($status) = &Apache::lonhomework::check_task_access('0'); |
|
if ($status eq 'CAN_ANSWER' || |
|
$status eq 'NEEDS_CHECKIN' || |
|
$status eq 'WAITING_FOR_GRADE') { |
|
&fail($r,'not_allowed'); |
|
return OK; |
|
} |
|
if ($env{'form.requestattempt'}) { |
|
&show_choices($r,$symb); |
|
} elsif ($env{'form.command'} eq 'release') { |
|
&release_slot($r,$symb); |
|
} elsif ($env{'form.command'} eq 'get') { |
|
&get_slot($r,$symb); |
|
} elsif ($env{'form.command'} eq 'change') { |
|
&release_slot($r,$symb,$env{'form.releaseslot'},1); |
|
&get_slot($r,$symb); |
|
} else { |
|
$r->print("<p>Unknown command: ".$env{'form.command'}."</p>"); |
|
} |
|
} |
&end_page($r); |
&end_page($r); |
return OK; |
return OK; |
} |
} |
|
|
|
1; |
|
__END__ |