File Coverage

blib/lib/Acme/Text/Rhombus.pm
Criterion Covered Total %
statement 56 61 91.8
branch 21 26 80.7
condition 8 9 88.8
subroutine 12 13 92.3
pod 4 4 100.0
total 101 113 89.3


line stmt bran cond sub pod time code
1             package Acme::Text::Rhombus;
2              
3 2     2   69277 use strict;
  2         10  
  2         56  
4 2     2   10 use warnings;
  2         5  
  2         51  
5 2     2   12 use base qw(Exporter);
  2         4  
  2         297  
6 2     2   21 use constant LINES => 25;
  2         4  
  2         228  
7 2     2   21 use constant FILLUP => '.';
  2         5  
  2         111  
8 2     2   12 use constant FORWARD => 1;
  2         4  
  2         2271  
9              
10             our ($VERSION, @EXPORT_OK, %EXPORT_TAGS);
11             my @subs;
12              
13             $VERSION = '0.25';
14             @subs = qw(rhombus rhombus_letter rhombus_digit rhombus_random);
15             @EXPORT_OK = @subs;
16             %EXPORT_TAGS = ('all' => [ @subs ]);
17              
18             my $get_opt = sub
19             {
20             my ($opts, $opt, $regex, $default) = @_;
21             return (exists $opts->{$opt}
22             && defined $opts->{$opt}
23             and $opts->{$opt} =~ $regex) ? $opts->{$opt} : $default;
24             };
25              
26             sub _draw_rhombus
27             {
28 5     5   18 my ($mode, $lines, $char, $case, $fillup, $forward) = @_;
29              
30 5         27 my ($is_letter, $is_digit, $is_random) = ($mode eq 'letter', $mode eq 'digit', $mode eq 'random');
31              
32             my %alter = (
33 2     2   8 lower => sub { lc $_[0] },
34 3     3   10 upper => sub { uc $_[0] },
35 5         25 );
36 5 100       15 $char = $alter{$case}->($char) if $is_letter;
37              
38 5         149 my @chars = map chr, (48..57, 65..90, 97..122);
39 5 50       15 $char = $chars[int(rand(@chars))] unless defined $char;
40              
41 5 50       13 $lines++ if $lines % 2 == 0;
42              
43 5         9 my ($line, $repeat, $rhombus);
44              
45 5         15 for ($line = $repeat = 1; $line <= $lines; $line++) {
46 117         176 my $spaces = ($lines - $repeat) / 2;
47              
48 117         170 $rhombus .= $fillup x $spaces;
49 117         180 $rhombus .= $char x $repeat;
50 117         150 $rhombus .= $fillup x $spaces;
51 117         134 $rhombus .= "\n";
52              
53 117 100       202 $repeat = $line < ($lines / 2) ? $repeat + 2 : $repeat - 2;
54              
55 117 100       183 if ($is_letter) {
    50          
    0          
56 71 100       125 $char = $forward ? chr(ord($char) + 1) : chr(ord($char) - 1);
57             }
58             elsif ($is_digit) {
59 46 100       72 $char = $forward ? $char + 1 : $char - 1;
60             }
61             elsif ($is_random) {
62 0         0 $char = $chars[int(rand(@chars))];
63             }
64              
65 117 100 100     533 if ($is_letter && $char !~ /[a-zA-Z]/) {
    100 100        
      66        
66 2 100       7 $char = $alter{$case}->($forward ? 'a' : 'z');
67             }
68             elsif ($is_digit and $char > 9 || $char < 0) {
69 5 100       13 $char = $forward ? 0 : 9;
70             }
71             }
72              
73 5         57 return $rhombus;
74             }
75              
76 1     1 1 94 sub rhombus { return rhombus_letter(@_); }
77              
78             sub rhombus_letter
79             {
80 3     3 1 26 my %opts = @_;
81              
82 3         20 my $lines = $get_opt->(\%opts, 'lines', qr/^\d+$/, LINES);
83 3         14 my $letter = $get_opt->(\%opts, 'letter', qr/^[a-zA-Z]$/, 'a');
84 3         13 my $case = $get_opt->(\%opts, 'case', qr/^(?:low|upp)er$/, 'upper');
85 3         13 my $fillup = $get_opt->(\%opts, 'fillup', qr/^\S$/, FILLUP);
86 3         10 my $forward = $get_opt->(\%opts, 'forward', qr/^[01]$/, FORWARD);
87              
88 3         13 return _draw_rhombus('letter', $lines, $letter, $case, $fillup, $forward);
89             }
90              
91             sub rhombus_digit
92             {
93 2     2 1 18 my %opts = @_;
94              
95 2         9 my $lines = $get_opt->(\%opts, 'lines', qr/^\d+$/, LINES);
96 2         7 my $digit = $get_opt->(\%opts, 'digit', qr/^\d$/, 0);
97 2         7 my $fillup = $get_opt->(\%opts, 'fillup', qr/^\S$/, FILLUP);
98 2         8 my $forward = $get_opt->(\%opts, 'forward', qr/^[01]$/, FORWARD);
99              
100 2         7 return _draw_rhombus('digit', $lines, $digit, undef, $fillup, $forward);
101             }
102              
103             sub rhombus_random
104             {
105 0     0 1   my %opts = @_;
106              
107 0           my $lines = $get_opt->(\%opts, 'lines', qr/^\d+$/, LINES);
108 0           my $fillup = $get_opt->(\%opts, 'fillup', qr/^\S$/, FILLUP);
109              
110 0           return _draw_rhombus('random', $lines, undef, undef, $fillup, undef);
111             }
112              
113             1;
114             __END__