App-War
view release on metacpan or search on metacpan
lib/App/War.pm view on Meta::CPAN
Get/set the items to be ranked. It's a bad idea to modify this once the
war has started.
=cut
sub items {
my $self = shift;
$self->{items} ||= [];
if (@_) {
$self->{items} = [shuffle @_];
}
return @{ $self->{items} };
}
=head2 $war->rank
Starts the process of uniquely ordering the graph vertices. This method
calls method C<tsort_not_unique> until it returns false, I<i.e.> we have a
unique topo sort.
=cut
sub rank {
my $self = shift;
while (my $v = $self->tsort_not_unique) {
$self->compare($v->[0], $v->[1]);
}
return $self;
}
=head2 $war->tsort_not_unique
This method returns a true value (more on this later) if the graph
currently lacks a unique topo sort. If the graph B<has> a unique sort, the
"war" is over, and results should be reported.
If the graph B<lacks> a unique topological sort, this method returns an
arrayref containing a pair of vertices that have an ambiguous ordering.
From L<http://en.wikipedia.org/wiki/Topological_sorting>:
=over 4
If a topological sort has the property that all pairs of consecutive
vertices in the sorted order are connected by edges, then these edges form
a directed Hamiltonian path in the DAG. If a Hamiltonian path exists, the
topological sort order is unique; no other order respects the edges of the
path.
=back
This property of the topological sort is used to ensure that we have a
unique ordering of the "combatants" in our "war".
=cut
sub tsort_not_unique {
my $self = shift;
# search for unordered items by calculating the topological sort and
# verifying that adjacent items are connected by a directed edge
my @ts = $self->graph->topological_sort;
for my $i (0 .. $#ts - 1) {
my ($u,$v) = @ts[$i,$i+1];
if (!$self->graph->has_edge($u,$v)) {
return [$u,$v];
}
}
return 0;
}
=head2 $war->compare($index1,$index2)
Handles user interaction choosing one of two alternatives. Arguments
C<$index1> and C<$index2> are indexes into the internal array of items to
be ranked, and indicate the two items that need to have their rank
disambiguated.
=cut
sub compare {
my ($self,@x) = @_;
my @items = $self->items;
my $response = $self->_get_response(@items[@x]);
if ($response =~ /1/) {
$self->graph->add_edge($x[0],$x[1]);
}
else {
$self->graph->add_edge($x[1],$x[0]);
}
}
sub _get_response {
my ($self,@items) = @_;
print "Choose one of the following:\n";
print "<1> $items[0]\n";
print "<2> $items[1]\n";
(my $resp = <STDIN>) =~ y/12//cd;
return $resp;
}
sub _info {
my $self = shift;
if ($self->{verbose}) {
warn "@_\n";
}
}
=head1 AUTHOR
John Trammell, C<< <johntrammell@gmail.com> >>
=head1 BUGS
Please report any bugs or feature requests to C<bug-app-war at
rt.cpan.org>, or through the web interface at
L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=App-War>. I will be
notified, and then you'll automatically be notified of progress on your bug
as I make changes.
( run in 2.103 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )