File Coverage

blib/lib/Game/Cribbage/Score.pm
Criterion Covered Total %
statement 15 15 100.0
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 20 20 100.0


line stmt bran cond sub pod time code
1             package Game::Cribbage::Score;
2              
3 7     7   49 use strict;
  7         15  
  7         264  
4 7     7   37 use warnings;
  7         14  
  7         431  
5              
6 7     7   42 use Rope;
  7         24  
  7         4379  
7 7     7   4769 use Rope::Autoload;
  7         18  
  7         44  
8 7     7   5036 use ntheory qw/forcomb vecsum/;
  7         107796  
  7         55  
9              
10             property total_score => (
11             initable => 1,
12             writeable => 1,
13             configurable => 0,
14             enumerable => 1
15             );
16              
17             property scored => (
18             initable => 1,
19             writeable => 0,
20             configurable => 0,
21             enumerable => 1,
22             value => {
23             fifteen => 2,
24             pair => 2,
25             three_of_a_kind => 6,
26             four_of_a_kind => 12,
27             run => [3, 4, 5],
28             four_flush => 4,
29             five_flush => 5,
30             nobs => 1
31             }
32             );
33              
34             property [qw/fifteen pair three_of_a_kind four_of_a_kind run four_flush five_flush nobs/] => (
35             initable => 1,
36             writeable => 0,
37             configurable => 1,
38             enumerable => 1,
39             value => []
40             );
41              
42             function INITIALISED => sub {
43             my ($self, $params) = @_;
44             my $starter = $params->{_cards}->[-1];
45             my @cards = sort { $b->value <=> $a->value } @{$params->{_cards}};
46             $self->calculate_fifteen(@cards);
47             $self->calculate_of_a_kind(@cards);
48             $self->calculate_run(@cards);
49             $self->calculate_flush(@cards);
50             $self->calculate_nob($starter, @cards) if $params->{_with_starter};
51             $self->calculate_total();
52             return $self;
53             };
54              
55             function calculate_nob => sub {
56             my ($self, $starter, @cards) = @_;
57              
58             return if ($starter->symbol eq 'J');
59              
60             for (@cards) {
61             if ($_->symbol eq 'J' && $starter->suit eq $_->suit) {
62             push @{$self->nobs}, $_;
63             last;
64             }
65             }
66             };
67              
68             function calculate_run => sub {
69             my ($self, @cards) = @_;
70              
71             my @values = map { $_->run_value } @cards;
72            
73             my %map;
74             foreach my $n (1 .. @values) {
75             forcomb {
76             my $first = $values[$_[0]];
77             my $match = 1;
78             return if scalar @_ < 3;
79             for (my $i = 1; $i < scalar(@_); $i++) {
80             $first = $first - 1;
81             if ($first != $values[$_[$i]]) {
82             $match = 0;
83             }
84             }
85             if ($match) {
86             if (scalar(@_) == 3) {
87             push @{$map{three}}, [@cards[@_]];
88             } elsif (scalar(@_) == 4) {
89             push @{$map{four}}, [@cards[@_]];
90             } else {
91             push @{$map{five}}, [@cards[@_]];
92             }
93             }
94             } @values, $n;
95             }
96            
97             if ($map{five}) {
98             $self->run = $map{five};
99             } elsif ($map{four}) {
100             $self->run = $map{four};
101             } elsif ($map{three}) {
102             $self->run = $map{three};
103             }
104             };
105              
106             function calculate_flush => sub {
107             my ($self, @cards) = @_;
108             my %map;
109             push @{$map{$_->suit}}, $_ for (@cards);
110             for (keys %map) {
111             my $c = scalar @{$map{$_}};
112             if ($c == 4) {
113             push @{$self->four_flush}, $map{$_};
114             } elsif ($c == 5) {
115             push @{$self->five_flush}, $map{$_};
116             }
117             }
118              
119             };
120              
121             function calculate_fifteen => sub {
122             my ($self, @cards) = @_;
123             my @values = map { $_->value } @cards;
124             foreach my $n (1 .. @values) {
125             forcomb {
126             push @{$self->fifteen}, [@cards[@_]] if vecsum(@values[@_]) == 15;
127             } @values, $n
128             }
129             };
130              
131             function calculate_of_a_kind => sub {
132             my ($self, @cards) = @_;
133             my %map = ();
134             push @{$map{$_->symbol}}, $_ for (@cards);
135             for (keys %map) {
136             my $c = scalar @{$map{$_}};
137             next if ($c == 1);
138             if ($c == 2) {
139             push @{$self->pair}, $map{$_};
140             } elsif ($c == 3) {
141             push @{$self->three_of_a_kind}, $map{$_};
142             } elsif ($c == 4) {
143             push @{$self->four_of_a_kind}, $map{$_};
144             }
145             }
146             };
147              
148             function calculate_total => sub {
149             my ($self) = @_;
150             my $scored = $self->scored;
151             my $score = 0;
152             for (keys %{$scored}) {
153             if (scalar @{$self->$_}) {
154             if ($_ eq 'run') {
155             $score += scalar @{$self->$_} * scalar @{$self->$_->[0]}
156             if $self->$_->[0];
157             } else {
158             $score += $scored->{$_} * scalar @{$self->$_};
159             }
160             }
161             }
162             $self->total_score = $score;
163             };
164              
165             1;