summaryrefslogtreecommitdiff
path: root/lib/GridFiller/Result.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/GridFiller/Result.pm')
-rw-r--r--lib/GridFiller/Result.pm144
1 files changed, 144 insertions, 0 deletions
diff --git a/lib/GridFiller/Result.pm b/lib/GridFiller/Result.pm
new file mode 100644
index 0000000..56ae3c2
--- /dev/null
+++ b/lib/GridFiller/Result.pm
@@ -0,0 +1,144 @@
+package GridFiller::Result;
+use Moose;
+use namespace::autoclean;
+use GridFiller::Types qw(GridT ResultT WordListT);
+use GridFiller::Constants ':directions';
+use Carp;
+
+with 'MooseX::Log::Log4perl';
+
+has leftover_words => (
+ isa => WordListT,
+ is => 'ro',
+ default => sub { [ ] },
+ traits => ['Array'],
+ handles => {
+ mark_leftover => 'push',
+ },
+);
+
+has grid => (
+ isa => ResultT,
+ is => 'ro',
+ lazy_build => 1,
+);
+
+has source_grid => (
+ isa => GridT,
+ is => 'ro',
+);
+
+{
+my %colourmap = (
+ '*' => {
+ $HORIZONTAL => {
+ 0 => 1,
+ 1 => 2,
+ },
+ $VERTICAL => {
+ 0 => 3,
+ 1 => 4,
+ },
+ },
+ ' ' => {
+ $HORIZONTAL => {
+ 0 => 5,
+ 1 => 6,
+ },
+ $VERTICAL => {
+ 0 => 7,
+ 1 => 8,
+ },
+ },
+);
+
+sub _build_grid {
+ return [
+ map {
+ [
+ map {
+ [ $colourmap{$_}->{$HORIZONTAL}->{0}, ' ' ],
+ } @$_
+ ]
+ } @{shift->source_grid}
+ ];
+}
+
+sub _find_colour_for {
+ my ($self,$x,$y,$dir) = @_;
+
+ my $parity = ($dir == $HORIZONTAL) ? ($y % 2) : ($x % 2);
+
+ my $chosen = $colourmap{$self->source_grid->[$y][$x]}->{$dir}->{$parity};
+
+ # avoid colour runs
+ if ( ( $x>0 && $dir == $HORIZONTAL && $self->grid->[$y][$x-1][0] == $chosen )
+ or
+ ( $y>0 && $dir == $VERTICAL && $self->grid->[$y-1][$x][0] == $chosen )
+ ) {
+ $chosen = $colourmap{$self->source_grid->[$y][$x]}->{$dir}->{1-$parity};
+ }
+
+ if (!defined $chosen) {
+ $self->log->warn(sprintf(q{Can't decide on colour for %d:%d (%s) direction %d},
+ $x,$y,$self->source_grid->[$y][$x],$dir));
+ }
+
+ return $chosen;
+}
+}
+
+sub place_word_at {
+ my ($self, $word, $x, $y, $dir) = @_;
+
+ my $colour = $self->_find_colour_for($x,$y,$dir);
+
+ $self->log->debug("Placing $word at ${x}:${y} ($dir) in colour $colour");
+
+ if ($dir == $HORIZONTAL) {
+ for my $i (0..length($word)-1) {
+ $self->_put_letter_at(substr($word,$i,1),
+ $x+$i,$y,
+ $colour);
+ }
+ }
+ elsif ($dir == $VERTICAL) {
+ for my $i (0..length($word)-1) {
+ $self->_put_letter_at(substr($word,$i,1),
+ $x,$y+$i,
+ $colour);
+ }
+ }
+ else {
+ croak "What dir $dir?";
+ }
+}
+
+sub _put_letter_at {
+ my ($self,$letter,$x,$y,$colour) = @_;
+
+ croak "undef colour" unless defined $colour;
+ croak "undef letter" unless defined $letter;
+
+ $self->grid->[$y][$x]=[$colour,$letter];
+ return;
+}
+
+sub to_string {
+ my ($self) = @_;
+
+ my $rows = scalar @{$self->grid};
+
+ my $str;
+
+ for my $row (0..$rows-1) {
+ for my $cell (@{$self->grid->[$row]}) {
+ $str .= $cell->[1] eq ' ' ? '.' : $cell->[1];
+ }
+ $str .= "\n";
+ }
+
+ return $str;
+}
+
+1;