File Coverage

blib/lib/Games/Sudoku/Component/Table/Permission.pm
Criterion Covered Total %
statement 61 68 89.7
branch 18 26 69.2
condition 1 4 25.0
subroutine 14 15 93.3
pod 7 7 100.0
total 101 120 84.1


line stmt bran cond sub pod time code
1             package Games::Sudoku::Component::Table::Permission;
2             {
3 7     7   50108 use strict;
  7         16  
  7         233  
4 7     7   41 use warnings;
  7         13  
  7         171  
5 7     7   32 use Carp;
  7         12  
  7         784  
6            
7             our $VERSION = '0.01';
8            
9 7     7   35 use base qw/Games::Sudoku::Component::Base/;
  7         13  
  7         6742  
10            
11             my $Verbose = 0;
12            
13             sub _initialize {
14 14     14   38 my ($this, %options) = @_;
15            
16 14         56 $this->clear;
17             }
18            
19 0     0 1 0 sub verbose { shift; $Verbose = shift; }
  0         0  
20            
21             sub clear {
22 15     15 1 42 my $this = shift;
23            
24 15         34 my $size = $this->{size};
25 15         40 my $flag = (2 ** $size) - 1;
26            
27 15         46 foreach my $ct (1..$size) {
28 151         266 $this->{row}[$ct] = $flag;
29 151         223 $this->{col}[$ct] = $flag;
30 151         323 $this->{blk}[$ct] = $flag;
31             }
32             }
33            
34             sub allow {
35 271     271 1 1267 my ($this, $row, $col, $value) = @_;
36            
37 271         853 my $blk = $this->_block_id($row,$col);
38            
39 271         716 $this->{row}[$row] = $this->_on($this->{row}[$row], $value);
40 271         650 $this->{col}[$col] = $this->_on($this->{col}[$col], $value);
41 271         619 $this->{blk}[$blk] = $this->_on($this->{blk}[$blk], $value);
42             }
43            
44             sub deny {
45 477     477 1 2128 my ($this, $row, $col, $value) = @_;
46            
47 477         1311 my $blk = $this->_block_id($row,$col);
48            
49 477         1557 $this->{row}[$row] = $this->_off($this->{row}[$row], $value);
50 477         1286 $this->{col}[$col] = $this->_off($this->{col}[$col], $value);
51 477         1166 $this->{blk}[$blk] = $this->_off($this->{blk}[$blk], $value);
52             }
53            
54             sub allowed {
55 8179     8179 1 12037 my ($this, $row, $col) = @_;
56            
57 8179         10635 my @allowed = ();
58 8179         15656 foreach my $ct (1..$this->{size}) {
59 64818 100       131000 push @allowed, $ct if $this->is_allowed($row, $col, $ct);
60             }
61 8179         58722 @allowed;
62             }
63            
64             sub is_allowed {
65 65406     65406 1 119045 my ($this, $row, $col, $value) = @_;
66            
67 65406         159284 my $blk = $this->_block_id($row, $col);
68            
69 65406 100       150269 return $this->result(
70             result => 0,
71             reason => "row $row has $value"
72             ) unless $this->_flag($this->{row}[$row], $value);
73            
74 59703 100       129173 return $this->result(
75             result => 0,
76             reason => "col $col has $value"
77             ) unless $this->_flag($this->{col}[$col], $value);
78            
79 44558 100       100053 return $this->result(
80             result => 0,
81             reason => "blk $blk has $value"
82             ) unless $this->_flag($this->{blk}[$blk], $value);
83            
84 42984         88697 return $this->result(1);
85             }
86            
87             sub result {
88 65416     65416 1 78996 my $this = shift;
89            
90 65416 50       108412 if ($Verbose) {
91 0         0 require Games::Sudoku::Component::Result;
92 0         0 my $result = Games::Sudoku::Component::Result->new(@_);
93             }
94             else {
95 65416 100       108679 if (@_ == 1) {
96 42984 50       76901 if (ref $_[0] eq 'HASH') {
97 0         0 my %options = %{ $_[0] };
  0         0  
98 0   0     0 return $options{result} || 0;
99             }
100             else {
101 42984         154132 return $_[0];
102             }
103             }
104             else {
105 22432         56160 my %options = @_;
106 22432   50     160562 return $options{result} || 0;
107             }
108             }
109             }
110            
111             sub _flag {
112 169694     169694   226735 my ($this, $flag, $value) = @_;
113            
114 169694 50       404851 croak "Invalid value: $value" unless $this->_check($value);
115 169694 50       302037 croak "Invalid flag: undef" unless defined $flag;
116            
117 169694         489885 return (0 + $flag) & (2 ** ($value - 1));
118             }
119            
120             sub _on {
121 814     814   1457 my ($this, $flag, $value) = @_;
122            
123 814 50       2135 croak "Invalid value: $value" unless $this->_check($value);
124 814 50       1520 croak "Invalid flag: undef" unless defined $flag;
125            
126 814         2433 return (0 + $flag) | (2 ** ($value - 1));
127             }
128            
129             sub _off {
130 1432     1432   2435 my ($this, $flag, $value) = @_;
131            
132 1432 50       3380 croak "Invalid value: $value" unless $this->_check($value);
133 1432 50       2647 croak "Invalid flag: undef" unless defined $flag;
134            
135 1432         4490 return (0 + $flag) & ~(2 ** ($value - 1));
136             }
137             }
138            
139             1;
140             __END__