File Coverage

blib/lib/Vote/Count/RankCount.pm
Criterion Covered Total %
statement 92 92 100.0
branch 5 6 83.3
condition n/a
subroutine 17 17 100.0
pod 0 8 0.0
total 114 123 92.6


line stmt bran cond sub pod time code
1 9     9   54 use strict;
  9         13  
  9         243  
2 9     9   38 use warnings;
  9         19  
  9         198  
3 9     9   160 use 5.022;
  9         28  
4              
5             package Vote::Count::RankCount;
6             $Vote::Count::RankCount::VERSION = '0.007'; # TRIAL
7 9     9   96 use feature qw /postderef signatures/;
  9         16  
  9         890  
8 9     9   49 no warnings 'experimental';
  9         18  
  9         298  
9 9     9   55 use List::Util qw( min max sum);
  9         15  
  9         582  
10 9     9   3025 use TextTableTiny qw/generate_markdown_table/;
  9         21  
  9         458  
11             # use boolean;
12 9     9   3135 use Data::Printer;
  9         143748  
  9         90  
13              
14 92     92   130 sub _RankResult ( $rawcount ) {
  92         142  
  92         108  
15 92         403 my %rc = $rawcount->%*; # destructive process needs to use a copy.
16 92         180 my %ordered = ();
17 92         150 my %byrank = () ;
18 92         129 my $pos = 0;
19 92         136 my $maxpos = scalar( keys %rc ) ;
20 92         190 while ( 0 < scalar( keys %rc ) ) {
21 400         464 $pos++;
22 400         661 my @vrc = values %rc;
23 400         750 my $max = max @vrc;
24 400         771 for my $k ( keys %rc ) {
25 1807 100       2580 if ( $rc{$k} == $max ) {
26 511         733 $ordered{$k} = $pos;
27 511         599 delete $rc{ $k };
28 511 100       766 if ( defined $byrank{$pos} ) {
29 111         161 push @{ $byrank{$pos} }, $k;
  111         293  
30             }
31             else {
32 400         952 $byrank{$pos} = [ $k ];
33             }
34             }
35             }
36 400 50       936 die "Vote::Count::RankCount::Rank in infinite loop\n" if
37             $pos > $maxpos ;
38             ;
39             }
40             # %byrank[1] is arrayref of 1st position,
41             # $pos still has last position filled, %byrank{$pos} is the last place.
42             # sometimes byranks came in as var{byrank...} deref and reref fixes this
43             # although it would be better if I understood why it happened.
44             # It is useful to sort the arrays anyway, for display they would likely be
45             # sorted anyway. For testing it makes the element order predictable.
46 92         125 my @top = sort @{$byrank{1}} ;
  92         259  
47 92         141 my @bottom = sort @{$byrank{ $pos }};
  92         299  
48             return {
49 92         468 'rawcount' => $rawcount,
50             'ordered' => \%ordered,
51             'byrank' => \%byrank,
52             'top' => \@top,
53             'bottom' => \@bottom,
54             };
55             }
56              
57 92     92 0 1468 sub Rank ( $class, $rawcount ) {
  92         130  
  92         125  
  92         133  
58 92         190 my $I = _RankResult( $rawcount);
59             # p $I;
60 92         448 return bless $I, $class;
61             }
62              
63 79     79 0 1223 sub RawCount ( $I ) { return $I->{'rawcount'} }
  79         98  
  79         92  
  79         250  
64 1     1 0 1412 sub HashWithOrder ( $I ) { return $I->{'ordered'} }
  1         2  
  1         1  
  1         3  
65 1     1 0 997 sub HashByRank ( $I ) { return $I->{'byrank'} }
  1         2  
  1         13  
  1         4  
66 2     2 0 2464 sub ArrayTop ( $I ) { return $I->{'top'} }
  2         5  
  2         79  
  2         11  
67 15     15 0 20 sub ArrayBottom ( $I ) { return $I->{'bottom'} }
  15         16  
  15         17  
  15         49  
68 64     64 0 396 sub CountVotes ($I) { return sum ( values $I->{'rawcount'}->%* )}
  64         75  
  64         79  
  64         275  
69             # sub ArrayTop ( $I ) { return [sort $I->{'top'}->@* ] }
70             # sub ArrayBottom ( $I ) { return [sort $I->{'bottom'}->@* ] }
71              
72 56     56 0 1333 sub RankTable( $self ) {
  56         74  
  56         70  
73 56         130 my @rows = ( [ 'Rank', 'Choice', 'Votes']);
74 56         198 my %rc = $self->{'rawcount'}->%*;
75 56         189 my %byrank = $self->{'byrank'}->%*;
76 56         206 for my $r ( sort keys %byrank ) {
77 223         395 my @choice = sort $byrank{$r}->@*;
78 223         300 for my $choice ( @choice ) {
79 277         337 my $votes = $rc{$choice};
80 277         422 my @row = ( $r, $choice, $votes );
81 277         510 push @rows, (\@row);
82             }
83             }
84 56         176 return generate_markdown_table( rows => \@rows );
85             }
86              
87             1;