File Coverage

lib/Games/Nonogram/Line.pm
Criterion Covered Total %
statement 59 73 80.8
branch 20 32 62.5
condition n/a
subroutine 13 15 86.6
pod 12 12 100.0
total 104 132 78.7


line stmt bran cond sub pod time code
1             package Games::Nonogram::Line;
2            
3 6     6   91617 use strict;
  6         13  
  6         236  
4 6     6   35 use warnings;
  6         10  
  6         179  
5 6     6   32 use base qw( Games::Nonogram::Base );
  6         25  
  6         5887  
6            
7             sub new {
8 9     9 1 44 my ($class, %options) = @_;
9            
10 9 50       42 my $size = $options{size} or die "size unknown";
11            
12 9         62 my $self = bless {
13             size => $size,
14             vec => '',
15             dirty => '',
16             is_done => 0,
17             }, $class;
18            
19 9         226 $self->clear;
20            
21 9         50 $self;
22             }
23            
24 31     31 1 258 sub size { shift->{size} }
25            
26             sub value {
27 464     464 1 565 my ($self, $id, $value) = @_;
28            
29 464 100       726 if ( defined $value ) {
30 94         140 my $prev = vec( $self->{vec}, $id, 2 );
31 94 100       239 if ( $prev != $value ) {
32 64         148 vec( $self->{vec}, $id, 2 ) = $value;
33 64         163 $self->is_dirty( $id );
34             }
35             }
36             else {
37 370         501 $value = vec( $self->{vec}, $id, 2 );
38 370 100       1219 $value > 1 ? -1 : $value;
39             }
40             }
41            
42             sub on {
43 37     37 1 40 my $self = shift;
44            
45 37 100       71 if ( @_ == 1 ) {
46 36         60 $self->value( shift, 1 );
47             }
48             else {
49 1         14 $self->value( $_ => 1 ) for ( $self->range( @_ ) );
50             }
51             }
52            
53             sub off {
54 53     53 1 61 my $self = shift;
55            
56 53 100       199 if ( @_ == 1 ) {
57 52         109 $self->value( shift, 0 );
58             }
59             else {
60 1         3 $self->value( $_ => 0 ) for ( $self->range( @_ ) );
61             }
62             }
63            
64             sub clear {
65 11     11 1 49 my ($self, $id) = @_;
66            
67 11 100       41 if ( defined $id ) {
68 1         5 vec( $self->{vec}, $id, 2 ) = -1;
69             }
70             else {
71 10         39 vec( $self->{vec}, $_, 2 ) = -1 for ( 1 .. $self->size );
72             }
73 11         31 $self->{is_done} = 0;
74             }
75            
76             sub is_done {
77 0     0 1 0 my $self = shift;
78            
79 0 0       0 return if $self->is_dirty;
80            
81 0 0       0 unless ( $self->{is_done} ) {
82 0         0 foreach my $ct ( 1 .. $self->size ) {
83 0 0       0 return if $self->value( $ct ) == -1;
84             }
85 0         0 $self->{is_done} = 1;
86             }
87 0         0 $self->{is_done};
88             }
89            
90             sub is_dirty {
91 114     114 1 1244 my ($self, $id) = @_;
92            
93 114 50       178 if ( defined $id ) {
94 114         384 vec( $self->{dirty}, $id, 1 ) = 1;
95             }
96             else {
97 0 0       0 return $self->{dirty} ne '' ? 1 : 0;
98             }
99             }
100            
101             sub dirty_items {
102 0     0 1 0 my $self = shift;
103            
104 0         0 my @dirty;
105 0         0 foreach my $ct ( 1 .. $self->size ) {
106 0 0       0 push @dirty, $ct if vec( $self->{dirty}, $ct, 1 );
107             }
108 0         0 $self->{dirty} = '';
109            
110 0         0 return @dirty;
111             }
112            
113             sub clone {
114 13     13 1 15 my $self = shift;
115            
116 13         13 my %clone = %{ $self };
  13         59  
117 13         56 bless \%clone, ref $self;
118             }
119            
120             sub as_vec {
121 10     10 1 12 my $self = shift;
122            
123 10 100       22 if ( @_ ) {
124 5         8 $self->{vec} = shift;
125 5         11 foreach my $ct ( 1 .. $self->size ) { $self->is_dirty( $ct ) }
  50         84  
126 5         10 $self->{is_done} = 0;
127             }
128 10         32 $self->{vec};
129             }
130            
131             sub as_string {
132 16     16 1 28 my $self = shift;
133            
134 16         65 my $str = '';
135 16         39 for my $ct ( 1 .. $self->size ) {
136 142         259 my $value = $self->value( $ct );
137 142 100       361 if ( $value == 0 ) {
    100          
138 45         73 $str .= '.';
139             }
140             elsif ( $value == 1 ) {
141 39         65 $str .= 'X';
142             }
143             else {
144 58         87 $str .= '_';
145             }
146             }
147 16         638 return $str;
148             }
149            
150             1;
151            
152             __END__