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   614 use strict;
  3         7  
  3         94  
4 3     3   14 use warnings;
  3         5  
  3         75  
5 3     3   52 use 5.024;
  3         12  
6 3     3   15 use feature qw /postderef signatures/;
  3         6  
  3         351  
7 3     3   20 use Storable 3.15 qw(dclone);
  3         44  
  3         139  
8              
9 3     3   42 use namespace::autoclean;
  3         6  
  3         21  
10              
11 3     3   293 no warnings 'experimental';
  3         6  
  3         207  
12              
13             our $VERSION='2.01';
14              
15             =head1 NAME
16              
17             Vote::Count::Redact
18              
19             =head1 VERSION 2.01
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   22 use Exporter::Easy ( OK => [qw( RedactSingle RedactPair RedactBullet )], );
  3         28  
  3         42  
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 9 sub RedactBullet ( $ballotset, @choices ) {
  4         8  
  4         10  
  4         8  
44 4         468 my $new = dclone($ballotset);
45 4         43 my %ballots = $new->{'ballots'}->%*;
46             REDACTBULLETLOOP:
47 4         22 for my $ballot ( keys %ballots ) {
48 32         55 my @newvote = ();
49 32         54 my $oldvote = $ballots{$ballot}->{'votes'}[0];
50 32 100       355 if ( grep( /^$oldvote$/, @choices ) ) {
51 8         34 $ballots{$ballot}->{'votes'} = [$oldvote];
52             }
53             }
54 4         19 $new->{'ballots'} = \%ballots;
55 4         45 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         4  
  2         4  
  2         2  
67 2         116 my $new = dclone($ballotset);
68 2         16 my %ballots = $new->{'ballots'}->%*;
69             REDACTSINGLELOOP:
70 2         8 for my $ballot ( keys %ballots ) {
71 22         24 my @newvote = ();
72 22         32 my @oldvote = $ballots{$ballot}{'votes'}->@*;
73 22         34 while (@oldvote) {
74 42         45 my $v = shift @oldvote;
75 42         50 push @newvote, $v;
76 42 100       54 if ( $v eq $A ) { @oldvote = () }
  6         7  
77             else { }
78 42         80 $ballots{$ballot}{'votes'} = \@newvote;
79             }
80 22         32 $ballots{$ballot}{'votes'} = \@newvote;
81             }
82 2         7 $new->{'ballots'} = \%ballots;
83 2         6 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 26 sub RedactPair ( $ballotset, $A, $B ) {
  10         22  
  10         24  
  10         17  
  10         19  
98 10         8352 my $new = dclone($ballotset);
99 10         482 my %ballots = $new->{'ballots'}->%*;
100             REDACTPAIRLOOP:
101 10         168 for my $ballot ( keys %ballots ) {
102 1182         1589 my @newvote = ();
103 1182         2913 my @oldvote = $ballots{$ballot}{'votes'}->@*;
104 1182         1967 while (@oldvote) {
105 2134         2912 my $v = shift @oldvote;
106 2134         3314 push @newvote, $v;
107 2134 100       3674 if ( $v eq $A ) {
    100          
108 578         894 while (@oldvote) {
109 957         1399 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       1424 if ( $u eq $B ) { @oldvote = () }
  386         743  
113 571         1079 else { push @newvote, ($u) }
114             }
115             }
116             elsif ( $v eq $B ) {
117 515         818 while (@oldvote) {
118 897         1304 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       1393 if ( $u eq $A ) { @oldvote = () }
  391         805  
122 506         937 else { push @newvote, ($u) }
123             }
124             }
125             else { }
126 2134         5181 $ballots{$ballot}{'votes'} = \@newvote;
127             }
128             }
129 10         296 $new->{'ballots'} = \%ballots;
130 10         57 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