File Coverage

blib/lib/App/Games/Keno.pm
Criterion Covered Total %
statement 52 72 72.2
branch 22 28 78.5
condition 7 12 58.3
subroutine 10 12 83.3
pod 0 4 0.0
total 91 128 71.0


line stmt bran cond sub pod time code
1             use Moose;
2 1     1   826 use Types::Standard qw(Int ArrayRef HashRef);
  1         412393  
  1         9  
3 1     1   7926 use Carp qw(croak);
  1         82634  
  1         14  
4 1     1   1084 use List::Compare qw (get_intersection);
  1         1  
  1         63  
5 1     1   839 use List::Util qw(any uniq);
  1         20061  
  1         48  
6 1     1   13 use Scalar::Util qw(looks_like_number);
  1         2  
  1         81  
7 1     1   6  
  1         2  
  1         827  
8             # ABSTRACT: Plays Keno
9              
10             =head1 NAME
11            
12             App::Games::Keno
13            
14             =head1 SYNOPSIS
15            
16             This package plays a game of Keno. The number range is 1 to 80 and the payout amounts are for 1 to 10 spots.
17            
18             Sample code to play 1000 draws with 5 spots. The spots are chosen for you.
19              
20             use App::Games::Keno;
21              
22             my $first_game = App::Games::Keno->new( num_spots => 5, draws => 1000 );
23             $first_game->PlayKeno;
24             say "You won \$"
25             . $first_game->winnings . " on "
26             . $first_game->draws
27             . " draws.";
28              
29             This is how you choose your own spots.
30              
31             my $second_game = App::Games::Keno->new(
32             spots => [ 45, 33, 12, 20, 75 ],
33             draws => 1000
34             );
35             $second_game->PlayKeno;
36             say "You won \$"
37             . $second_game->winnings . " on "
38             . $second_game->draws
39             . " draws.";
40              
41             =cut
42              
43             my $self = shift;
44              
45 14     14 0 15532 croak "Didn't get the number of draws you want"
46             if ( !defined $self->draws );
47 14 100       357 croak "Spots or Number of spots (not both)"
48             if ( defined $self->spots && defined $self->num_spots );
49 13 100 100     269 croak "Need spots or number of spots"
50             if ( !defined $self->spots && !defined $self->num_spots );
51 12 100 100     249  
52             if ( defined $self->spots ) {
53             if ( any { !looks_like_number($_) } @{ $self->spots } ) {
54 11 100 33     217 croak "One of the spots you chose doesn't look like a number.";
    50          
55 10 100   27   49 }
  27         55  
  10         200  
56 1         199 if ( any { $_ < 1 || $_ > 80 } @{ $self->spots } ) {
57             croak "You chose a spot that is out of the 1 to 80 range";
58 9 100   25   42 }
  25 100       67  
  9         184  
59 3         380 if ( scalar @{ $self->spots } != uniq @{ $self->spots } ) {
60             croak "You appear to have chosen two or more of the same spots";
61 6 100       13 }
  6         124  
  6         118  
62 1         114 if ( scalar @{ $self->spots } < 1 ) {
63             croak "You must choose at least one spot";
64 5 100       11 }
  5         102  
65 1         107 if ( my $too_many_spots = scalar @{ $self->spots } > 10 ) {
66             croak "Too many spots. You must choose between 1 and 10 spots";
67 4 100       8 }
  4         96  
68 1         120 $self->num_spots( scalar @{ $self->spots } );
69             }
70 3         6 elsif ( $self->num_spots >= 1 && $self->num_spots <= 10 ) {
  3         108  
71             $self->spots( get_random_set( $self->num_spots ) );
72             }
73 1         22 else {
74             croak "You must ask for between 1 and 10 spots.";
75             }
76 0         0  
77             return;
78             }
79 4         13  
80             has 'draws' => (
81             is => 'rw',
82             isa => Int,
83             );
84              
85             has 'winnings' => (
86             is => 'rw',
87             isa => Int,
88             default => 0
89             );
90              
91             has 'num_won_draws' => (
92             is => 'rw',
93             isa => Int,
94             default => 0
95             );
96              
97             has 'num_spots' => (
98             is => 'rw',
99             isa => Int,
100             );
101              
102             has 'spots' => (
103             is => 'rw',
104             isa => ArrayRef,
105             );
106              
107             has 'payout_table' => (
108             is => 'ro',
109             isa => HashRef,
110             default => sub {
111             return {
112             '1' => {
113             '1' => 2
114             },
115             '2' => {
116             '2' => 11
117             },
118             '3' => {
119             '2' => 2,
120             '3' => 27
121             },
122             '4' => {
123             '2' => 1,
124             '3' => 5,
125             '4' => 75
126             },
127             '5' => {
128             '3' => 2,
129             '4' => 18,
130             '5' => 420
131             },
132             '6' => {
133             '3' => 1,
134             '4' => 8,
135             '5' => 50,
136             '6' => 1100,
137             },
138             '7' => {
139             '3' => 1,
140             '4' => 3,
141             '5' => 17,
142             '6' => 100,
143             '7' => 4500
144             },
145             '8' => {
146             '4' => 2,
147             '5' => 12,
148             '6' => 50,
149             '7' => 750,
150             '8' => 10_000
151             },
152             '9' => {
153             '4' => 1,
154             '5' => 6,
155             '6' => 25,
156             '7' => 150,
157             '8' => 3000,
158             '9' => 30_000,
159             },
160             '10' => {
161             '0' => 5,
162             '5' => 2,
163             '6' => 15,
164             '7' => 40,
165             '8' => 450,
166             '9' => 4250,
167             '10' => 100_000
168             }
169             };
170             }
171             );
172              
173             my $self = shift;
174             for ( 1 .. $self->draws ) {
175             my $drawnNumbers = get_random_set(20);
176 0     0 0 0 my $list_compare = List::Compare->new( $self->spots, $drawnNumbers );
177 0         0 my @matchedNumbers = $list_compare->get_intersection;
178 0         0 my $matches = scalar @matchedNumbers;
179 0         0 my $this_payout = $self->get_payout($matches);
180 0         0 my $winningsIn = $self->winnings;
181 0         0 if ( $matches > 6 && $matches == $self->num_spots ) {
182 0         0 print
183 0         0 "You matched all $matches spots and won \$$this_payout on draw $_\n";
184 0 0 0     0 }
185 0         0 my $winningsOut = $winningsIn += $this_payout;
186             $self->winnings($winningsOut);
187             }
188 0         0 return;
189 0         0 }
190              
191 0         0 my $count = shift;
192             my @random_set;
193             my %seen;
194              
195 1     1 0 23 for ( 1 .. $count ) {
196 1         7 my $candidate = 1 + int rand(80);
197             redo if $seen{$candidate}++;
198             push @random_set, $candidate;
199 1         9 }
200 5         11  
201 5 50       14 return \@random_set;
202 5         10 }
203              
204             my $self = shift;
205 1         30 my $match = shift;
206             my $spot = $self->num_spots;
207              
208             if ( exists( $self->payout_table->{$spot}{$match} ) ) {
209 0     0 0   return $self->payout_table->{$spot}{$match};
210 0           }
211 0           else {
212             return 0;
213 0 0         }
214 0           }
215              
216             1;
217 0