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             package Vote::Count::Redact;
2              
3 3     3   547 use strict;
  3         8  
  3         103  
4 3     3   18 use warnings;
  3         7  
  3         83  
5 3     3   52 use 5.024;
  3         11  
6 3     3   19 use feature qw /postderef signatures/;
  3         8  
  3         326  
7 3     3   24 use Storable 3.15 qw(dclone);
  3         44  
  3         161  
8              
9 3     3   38 use namespace::autoclean;
  3         8  
  3         28  
10              
11 3     3   370 no warnings 'experimental';
  3         18  
  3         223  
12              
13             our $VERSION='2.00';
14              
15             =head1 NAME
16              
17             Vote::Count::Redact
18              
19             =head1 VERSION 2.00
20              
21             Methods for Redacting Ballots.
22              
23             =head2 Purpose
24              
25             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.
26              
27             use Vote::Count::Redact qw/RedactPair RedactBullet RedactSingle/;
28              
29             =cut
30              
31             # ABSTRACT: Methods for Redacting Vote::Count BallotSets.
32              
33 3     3   19 use Exporter::Easy ( OK => [qw( RedactSingle RedactPair RedactBullet )], );
  3         8  
  3         25  
34              
35             =head2 RedactBullet
36              
37             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.
38              
39             my $newBallotSet = RedactBullet( $Election->BallotSet(), 'A', 'B', 'F');
40              
41             =cut
42              
43 4     4 1 10 sub RedactBullet ( $ballotset, @choices ) {
  4         7  
  4         12  
  4         8  
44 4         263 my $new = dclone($ballotset);
45 4         33 my %ballots = $new->{'ballots'}->%*;
46             REDACTBULLETLOOP:
47 4         23 for my $ballot ( keys %ballots ) {
48 32         58 my @newvote = ();
49 32         57 my $oldvote = $ballots{$ballot}->{'votes'}[0];
50 32 100       366 if ( grep( /^$oldvote$/, @choices ) ) {
51 8         31 $ballots{$ballot}->{'votes'} = [$oldvote];
52             }
53             }
54 4         19 $new->{'ballots'} = \%ballots;
55 4         48 return $new;
56             }
57              
58             =head2 RedactSingle
59              
60             Return a new BallotSet truncating the ballots after the given choice.
61              
62             my $newBallotSet = RedactSingle( $VoteCountObject->BallotSet(), $choice);
63              
64             =cut
65              
66 2     2 1 4 sub RedactSingle ( $ballotset, $A ) {
  2         5  
  2         3  
  2         3  
67 2         177 my $new = dclone($ballotset);
68 2         20 my %ballots = $new->{'ballots'}->%*;
69             REDACTSINGLELOOP:
70 2         11 for my $ballot ( keys %ballots ) {
71 22         28 my @newvote = ();
72 22         39 my @oldvote = $ballots{$ballot}{'votes'}->@*;
73 22         40 while (@oldvote) {
74 42         57 my $v = shift @oldvote;
75 42         63 push @newvote, $v;
76 42 100       66 if ( $v eq $A ) { @oldvote = () }
  6         9  
77             else { }
78 42         88 $ballots{$ballot}{'votes'} = \@newvote;
79             }
80 22         40 $ballots{$ballot}{'votes'} = \@newvote;
81             }
82 2         8 $new->{'ballots'} = \%ballots;
83 2         7 return $new;
84             }
85              
86             =head2 RedactPair
87              
88             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.
89              
90             my $newBallotSet = RedactPair( $VoteCountObject->BallotSet(), 'A', 'B');
91              
92             =cut
93              
94             # RedactPair only alters votes involving the two choices
95             # The other two methods truncate after the choice.
96              
97 10     10 1 28 sub RedactPair ( $ballotset, $A, $B ) {
  10         23  
  10         21  
  10         29  
  10         17  
98 10         8801 my $new = dclone($ballotset);
99 10         497 my %ballots = $new->{'ballots'}->%*;
100             REDACTPAIRLOOP:
101 10         180 for my $ballot ( keys %ballots ) {
102 1182         1566 my @newvote = ();
103 1182         2826 my @oldvote = $ballots{$ballot}{'votes'}->@*;
104 1182         2079 while (@oldvote) {
105 2134         2992 my $v = shift @oldvote;
106 2134         3216 push @newvote, $v;
107 2134 100       3753 if ( $v eq $A ) {
    100          
108 578         965 while (@oldvote) {
109 957         1310 my $u = shift @oldvote;
110             # If the other redaction member is the present vote
111             # truncate this vote from here on by setting oldvote to empty array.
112 957 100       1502 if ( $u eq $B ) { @oldvote = () }
  386         753  
113 571         1148 else { push @newvote, ($u) }
114             }
115             }
116             elsif ( $v eq $B ) {
117 515         844 while (@oldvote) {
118 897         1251 my $u = shift @oldvote;
119             # If the other redaction member is the present vote
120             # truncate this vote from here on by setting oldvote to empty array.
121 897 100       1380 if ( $u eq $A ) { @oldvote = () }
  391         773  
122 506         993 else { push @newvote, ($u) }
123             }
124             }
125             else { }
126 2134         4927 $ballots{$ballot}{'votes'} = \@newvote;
127             }
128             }
129 10         309 $new->{'ballots'} = \%ballots;
130 10         62 return $new;
131             }
132              
133             1;
134              
135             #FOOTER
136              
137             =pod
138              
139             BUG TRACKER
140              
141             L<https://github.com/brainbuz/Vote-Count/issues>
142              
143             AUTHOR
144              
145             John Karr (BRAINBUZ) brainbuz@cpan.org
146              
147             CONTRIBUTORS
148              
149             Copyright 2019-2021 by John Karr (BRAINBUZ) brainbuz@cpan.org.
150              
151             LICENSE
152              
153             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>.
154              
155             SUPPORT
156              
157             This software is provided as is, per the terms of the GNU Public License. Professional support and customisation services are available from the author.
158              
159             =cut
160