diff options
author | dakkar <dakkar@thenautilus.net> | 2010-11-25 21:16:35 +0000 |
---|---|---|
committer | dakkar <dakkar@thenautilus.net> | 2010-11-25 21:16:35 +0000 |
commit | 26f864e4b84dfae2364b6e7f42818df2b4ec5f1e (patch) | |
tree | dafd3bddd139049acfb4eccdf56a015abc3bb3e4 /lib/GridFiller/Status.pm | |
parent | use the real data (diff) | |
download | qr-builder-26f864e4b84dfae2364b6e7f42818df2b4ec5f1e.tar.gz qr-builder-26f864e4b84dfae2364b6e7f42818df2b4ec5f1e.tar.bz2 qr-builder-26f864e4b84dfae2364b6e7f42818df2b4ec5f1e.zip |
big refactoring
Diffstat (limited to 'lib/GridFiller/Status.pm')
-rw-r--r-- | lib/GridFiller/Status.pm | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/lib/GridFiller/Status.pm b/lib/GridFiller/Status.pm new file mode 100644 index 0000000..873d252 --- /dev/null +++ b/lib/GridFiller/Status.pm @@ -0,0 +1,198 @@ +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; + +with 'MooseX::Log::Log4perl'; + +has words_to_use => ( + isa => WordListT, + traits => ['Array'], + handles => { + has_next_word => 'count', + get_next_word => 'shift', + }, + is => 'rw', +); + +has grid_status => ( + isa => GridStatusT, + is => 'rw', +); + +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->{grid_status} = _munge_grid_status(delete $args->{grid}); + } + + return $class->$orig($args,@rest); +}; + +sub _munge_words_to_use { + my $words=shift; + # clone initial word list + return [ shuffle uniq @$words ]; +} + +sub _munge_grid_status { + my $grid=shift; + 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; +} + +sub find_place_for { + my ($self,$word) = @_; + + my $dir = int(rand(2)) ? $HORIZONTAL : $VERTICAL; + + my $length = length $word; + + my @ret; + + if ($dir == $HORIZONTAL) { + @ret = $self->_find_place_horiz($length); + @ret = $self->_find_place_vert($length) unless @ret; + } + else { + @ret = $self->_find_place_vert($length); + @ret = $self->_find_place_horiz($length) unless @ret; + } + + return @ret; +} + +sub _find_place_horiz { + my ($self,$length) = @_; + + my $rows = scalar @{$self->grid_status}; + my $col; + + for my $row (0..$rows-1) { + $col = $self->_find_in_row($row,$length); + return ($col,$row,$HORIZONTAL) if defined $col; + } + return; +} + +sub _find_place_vert { + my ($self,$length) = @_; + + my $cols = scalar @{$self->grid_status->[0]}; + my $row; + + for my $col (0..$cols-1) { + $row = $self->_find_in_col($col,$length); + return ($col,$row,$VERTICAL) if defined $row; + } + return; +} + +{ +my %symbols=( + $NOTHING => ' ', + $BLACK => 'X', + $WHITE => 'O', +); + +sub _do_find { + my ($self,$str,$length) = @_; + + my ($skip) = ($str =~ m{^ (.*?) (?: X{$length} | O{$length} ) }x); + + $self->log->debug(defined $skip ? " skip <$skip>" : " nope"); + + return length($skip) if defined $skip; + return; +} + +sub _find_in_row { + my ($self,$row,$length) = @_; + + my $str = join '',map { $symbols{$_} } @{$self->grid_status->[$row]}; + + $self->log->debug("row $row = $str"); + + return $self->_do_find($str,$length); +} + +sub _find_in_col { + my ($self,$col,$length) = @_; + + my $str = join '',map { $symbols{$_->[$col]} } @{$self->grid_status}; + + $self->log->debug("col $col = $str"); + + return $self->_do_find($str,$length); +} + +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; |