File Coverage

blib/lib/Vote/Count/Redact.pm
Criterion Covered Total %
statement 81 81 100.0
branch 12 12 100.0
condition n/a
subroutine 11 11 100.0
pod 3 3 100.0
total 107 107 100.0


line stmt bran cond sub pod time code
1              
2             use strict;
3 3     3   477 use warnings;
  3         6  
  3         93  
4 3     3   15 use 5.024;
  3         9  
  3         75  
5 3     3   48 use feature qw /postderef signatures/;
  3         12  
6 3     3   18 use Storable 3.15 qw(dclone);
  3         6  
  3         278  
7 3     3   20  
  3         41  
  3         158  
8             use namespace::autoclean;
9 3     3   22  
  3         5  
  3         24  
10             no warnings 'experimental';
11 3     3   319  
  3         6  
  3         229  
12             our $VERSION='2.02';
13              
14             =head1 NAME
15              
16             Vote::Count::Redact
17              
18             =head1 VERSION 2.02
19              
20             Methods for Redacting Ballots.
21              
22             =head2 Purpose
23              
24             Redacting Ballots is useful for what-if analysis and identifying Later Harm effects. Compound Methods seeking to reduce Later Harm effects can also be developed using this technique.
25              
26             use Vote::Count::Redact qw/RedactPair RedactBullet RedactSingle/;
27              
28             =cut
29              
30             # ABSTRACT: Methods for Redacting Vote::Count BallotSets.
31              
32             use Exporter::Easy ( OK => [qw( RedactSingle RedactPair RedactBullet )], );
33 3     3   21  
  3         8  
  3         30  
34             =head2 RedactBullet
35              
36             Takes a list (array) of choices to be converted to bullet votes. Returns a modified BallotSet where all votes that had a first choice vote for a member of the list are votes for only that choice.
37              
38             my $newBallotSet = RedactBullet( $Election->BallotSet(), 'A', 'B', 'F');
39              
40             =cut
41              
42             my $new = dclone($ballotset);
43 4     4 1 10 my %ballots = $new->{'ballots'}->%*;
  4         11  
  4         10  
  4         15  
44 4         319 REDACTBULLETLOOP:
45 4         39 for my $ballot ( keys %ballots ) {
46             my @newvote = ();
47 4         22 my $oldvote = $ballots{$ballot}->{'votes'}[0];
48 32         58 if ( grep( /^$oldvote$/, @choices ) ) {
49 32         60 $ballots{$ballot}->{'votes'} = [$oldvote];
50 32 100       371 }
51 8         35 }
52             $new->{'ballots'} = \%ballots;
53             return $new;
54 4         21 }
55 4         47  
56             =head2 RedactSingle
57              
58             Return a new BallotSet truncating the ballots after the given choice.
59              
60             my $newBallotSet = RedactSingle( $VoteCountObject->BallotSet(), $choice);
61              
62             =cut
63              
64             my $new = dclone($ballotset);
65             my %ballots = $new->{'ballots'}->%*;
66 2     2 1 3 REDACTSINGLELOOP:
  2         5  
  2         3  
  2         3  
67 2         131 for my $ballot ( keys %ballots ) {
68 2         17 my @newvote = ();
69             my @oldvote = $ballots{$ballot}{'votes'}->@*;
70 2         10 while (@oldvote) {
71 22         48 my $v = shift @oldvote;
72 22         38 push @newvote, $v;
73 22         44 if ( $v eq $A ) { @oldvote = () }
74 42         57 else { }
75 42         67 $ballots{$ballot}{'votes'} = \@newvote;
76 42 100       61 }
  6         12  
77             $ballots{$ballot}{'votes'} = \@newvote;
78 42         90 }
79             $new->{'ballots'} = \%ballots;
80 22         37 return $new;
81             }
82 2         8  
83 2         7 =head2 RedactPair
84              
85             For a Ballot Set and two choices, on each ballot where both appear it removes the later one and all subsequent choices, returning a completely independent new BallotSet. If the later choices were left intact, they would become votes against the redacted choices in those pairings.
86              
87             my $newBallotSet = RedactPair( $VoteCountObject->BallotSet(), 'A', 'B');
88              
89             =cut
90              
91             # RedactPair only alters votes involving the two choices
92             # The other two methods truncate after the choice.
93              
94             my $new = dclone($ballotset);
95             my %ballots = $new->{'ballots'}->%*;
96             REDACTPAIRLOOP:
97 10     10 1 23 for my $ballot ( keys %ballots ) {
  10         19  
  10         25  
  10         20  
  10         18  
98 10         7223 my @newvote = ();
99 10         396 my @oldvote = $ballots{$ballot}{'votes'}->@*;
100             while (@oldvote) {
101 10         177 my $v = shift @oldvote;
102 1182         1584 push @newvote, $v;
103 1182         2412 if ( $v eq $A ) {
104 1182         1963 while (@oldvote) {
105 2134         2952 my $u = shift @oldvote;
106 2134         3039 # If the other redaction member is the present vote
107 2134 100       3723 # truncate this vote from here on by setting oldvote to empty array.
    100          
108 578         934 if ( $u eq $B ) { @oldvote = () }
109 957         1288 else { push @newvote, ($u) }
110             }
111             }
112 957 100       1392 elsif ( $v eq $B ) {
  386         729  
113 571         1087 while (@oldvote) {
114             my $u = shift @oldvote;
115             # If the other redaction member is the present vote
116             # truncate this vote from here on by setting oldvote to empty array.
117 515         850 if ( $u eq $A ) { @oldvote = () }
118 897         1226 else { push @newvote, ($u) }
119             }
120             }
121 897 100       1382 else { }
  391         753  
122 506         937 $ballots{$ballot}{'votes'} = \@newvote;
123             }
124             }
125             $new->{'ballots'} = \%ballots;
126 2134         4880 return $new;
127             }
128              
129 10         146 1;
130 10         47  
131             #FOOTER
132              
133             =pod
134              
135             BUG TRACKER
136              
137             L<https://github.com/brainbuz/Vote-Count/issues>
138              
139             AUTHOR
140              
141             John Karr (BRAINBUZ) brainbuz@cpan.org
142              
143             CONTRIBUTORS
144              
145             Copyright 2019-2021 by John Karr (BRAINBUZ) brainbuz@cpan.org.
146              
147             LICENSE
148              
149             This module is released under the GNU Public License Version 3. See license file for details. For more information on this license visit L<http://fsf.org>.
150              
151             SUPPORT
152              
153             This software is provided as is, per the terms of the GNU Public License. Professional support and customisation services are available from the author.
154              
155             =cut
156