package GridFiller::Status;
use Moose;
use namespace::autoclean;
use List::Util qw(shuffle);
use List::MoreUtils qw(uniq);
use GridFiller::Types qw(WordListT GridStatusT);
use GridFiller::Constants ':all';
use Carp;
use feature 'switch';
with 'MooseX::Log::Log4perl';
has words_to_use => (
isa => WordListT,
traits => ['Array'],
handles => {
has_next_word => 'count',
get_next_word => 'shift',
},
is => 'rw',
required => 1,
);
has grid_status => (
isa => GridStatusT,
is => 'rw',
required => 1,
);
around BUILDARGS => sub {
my ($orig, $class, $args, @rest) = @_;
if (exists $args->{words} && exists $args->{grid}) {
$args->{words_to_use} = _munge_words_to_use(delete $args->{words},$args);
$args->{grid_status} = _munge_grid_status(delete $args->{grid});
}
return $class->$orig($args,@rest);
};
sub _munge_words_to_use {
my ($words,$args) = @_;
my $mode = delete $args->{mode} || 'random';
given ($mode) {
when ('random') { return [ shuffle uniq @$words ] }
when ('given') { return [ uniq @$words ] }
when ('longest') { return [ sort {length($b) <=> length($a)} uniq @$words ] }
when ('shortest') { return [ sort {length($a) <=> length($b)} uniq @$words ] }
default { croak "Unknown mode $mode" }
}
}
sub _munge_grid_status {
my ($grid) = @_;
return [
map {
[
map {
$_ eq '*' ? $BLACK : $WHITE
} @$_
]
} @$grid
];
}
sub place_word_at {
my ($self, $word, $x, $y, $dir) = @_;
$self->log->debug("Marking <$word> occupied at ${x}:${y} ($dir)");
if ($dir == $HORIZONTAL) {
for my $i (0..length($word)-1) {
$self->_mark_occupied($x+$i,$y);
}
}
elsif ($dir == $VERTICAL) {
for my $i (0..length($word)-1) {
$self->_mark_occupied($x,$y+$i);
}
}
else {
croak "What dir $dir?";
}
}
sub _mark_occupied {
my ($self,$x,$y) = @_;
$self->grid_status->[$y][$x]=$NOTHING;
return;
}
sub unfilled {
my ($self) = @_;
for my $row (@{$self->grid_status}) {
for my $cell (@$row) {
return 1 if $cell != $NOTHING;
}
}
return 0;
}
{
my %symbols=(
$NOTHING => ' ',
$BLACK => 'X',
$WHITE => 'O',
);
sub to_string {
my ($self) = @_;
my $rows = scalar @{$self->grid_status};
my $str;
for my $row (0..$rows-1) {
for my $cell (@{$self->grid_status->[$row]}) {
$str .= $symbols{$cell};
}
$str .= "\n";
}
return $str;
}
}
1;