Acme-Urinal
view release on metacpan or search on metacpan
lib/Acme/Urinal.pm view on Meta::CPAN
sub pick_one {
my ($self) = @_;
my $choice_score = 0;
my $best_choice;
for my $i (0 .. $#$self) {
my ($in_use, $resource) = @{ $self->[$i] };
next if $in_use;
if ($choice_score < 5 and $i > 0 and $i < $#$self and not($self->[$i - 1][0]) and not($self->[$i + 1][0])) {
$choice_score = 5;
$best_choice = $i;
last;
}
elsif ($choice_score < 4 and $i > 0 and not $self->[$i - 1][0]) {
$choice_score = 4;
$best_choice = $i;
}
elsif ($choice_score < 3 and $i < $#$self and not $self->[$i + 1][0]) {
$choice_score = 3;
$best_choice = $i;
}
elsif ($choice_score < 2 and $i > 0 and $i < $#$self) {
$choice_score = 2;
$best_choice = $i
}
elsif ($choice_score < 1) {
$choice_score = 1;
$best_choice = $i;
}
}
if (defined $best_choice) {
$self->[$best_choice][0] = 1;
if (wantarray) {
return ($best_choice, $self->[$best_choice][1], $choice_score);
}
else {
return $best_choice;
}
}
return;
}
=head2 pick
my $resource = $self->pick($index);
my ($resource, $comfort_level) = $self->pick($index);
Allows you to violate the usual algorithm to pick a urinal explicitly. In scalar
context it returns the resource picked. In list context, it returns that and the
comfort level your pick has. If the resource picked is already in use, an
exception will be thrown.
=cut
sub pick {
my ($self, $i) = @_;
if ($self->[$i][0]) {
croak "The resource at index $i is already in use.";
}
if (wantarray) {
my @r = $self->look($i);
$self->[$i][0] = 1;
return @r;
}
else {
my $r = $self->look($i);
$self->[$i][0] = 1;
return $r;
}
}
=head2 look
my $resource = $self->look($index);
my ($resource, $comfort_level) = $self->look($index);
In most algorithms, this would be called "peek," but peeking in urinals is, at
best, awkward and, at worst, likely to get you beat up.
This is the same as L</pick>, but does not actually allocate. Also, the
C<$comfort_level> returned will be C<0> if the resource is currently in use.
=cut
sub look {
my ($self, $i) = @_;
if (wantarray) {
my $choice_score = 0;
if (not $self->[$i][0]) {
if ($i > 0 and $i < $#$self and not $self->[$i - 1][0] and not $self->[$i + 1][0]) {
$choice_score = 5;
}
elsif ($i > 0 and not $self->[$i - 1][0]) {
$choice_score = 4;
}
elsif ($i < $#$self and not $self->[$i + 1][0]) {
$choice_score = 3;
}
elsif ($i > 0 and $i < $#$self) {
$choice_score = 2;
}
else {
$choice_score = 1;
}
( run in 1.089 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )