aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin H. Johnson <robbat2@gentoo.org>2021-06-17 23:56:42 -0700
committerRobin H. Johnson <robbat2@gentoo.org>2021-06-17 23:56:42 -0700
commit8e9679101b638f65af8be2e034263efed09bf22e (patch)
tree32efacbe186552bb1594f228390628ea56cb5ce4
parentREADME.md: refresh docs (diff)
downloadelections-8e967910.tar.gz
elections-8e967910.tar.bz2
elections-8e967910.zip
Votify: improvements from re-using the codebase for another project
Signed-off-by: Robin H. Johnson <robbat2@gentoo.org>
-rw-r--r--Votify.pm49
-rwxr-xr-xcountify19
2 files changed, 48 insertions, 20 deletions
diff --git a/Votify.pm b/Votify.pm
index 87fba2f..35a717f 100644
--- a/Votify.pm
+++ b/Votify.pm
@@ -8,13 +8,13 @@
package Votify;
-use POSIX;
+use Carp::Always;
use Cwd qw(abs_path);
+use Data::Dumper;
use File::Basename;
use File::Spec::Functions;
use List::Util;
-use Data::Dumper;
-use Carp::Always;
+use POSIX;
use strict;
use warnings;
@@ -218,8 +218,8 @@ sub new {
close(F);
# assign confirmation numbers randomly
- for my $v (@voterlist) {
- do { $r = int rand 0xffff } while exists $self->{'voters'}{$r};
+ for my $v (List::Util::shuffle(@voterlist)) {
+ do { $r = int rand 0xffffffff } while exists $self->{'voters'}{$r};
$self->{'voters'}{$r} = $v;
$self->{'confs'}{$v} = $r;
}
@@ -239,7 +239,7 @@ sub confs {
sub voters {
my ($self) = @_;
- sort keys %{$self->{'confs'}};
+ return sort keys %{$self->{'confs'}};
}
sub getvoter {
@@ -252,7 +252,7 @@ sub getconf {
return $self->{'confs'}{$voter};
}
-sub write {
+sub write_confs {
my ($self, $filename) = @_;
$filename ||= $self->{'default_filename'};
@@ -263,8 +263,8 @@ sub write {
}
open(F, ">$filename") or die("can't write to $filename");
- for my $c ($self->confs) {
- printf F "%04x %s\n", $c, $self->getvoter($c);
+ for my $c (sort { $a <=> $b } map { int $_ } $self->confs) {
+ printf F "%08x %s\n", $c, $self->getvoter($c);
}
close F;
}
@@ -287,6 +287,7 @@ sub new {
default_filename => catfile($datadir, "master-$election_name"),
filename => '',
voterlist => $vl,
+ casting_voters => {}, # indexed by voter
ballots => {}, # indexed by conf num
candidates => undef, # indexed by long name
table => undef, # indexed by row+column
@@ -326,6 +327,7 @@ sub collect {
next;
}
$self->{'ballots'}{$c} = $b;
+ $self->{'casting_voters'}{$v} = 1;
}
elsif (-f "$home/.ballot-$self->{election}") {
print STDERR "Warning: $v did not submit their ballot\n";
@@ -333,7 +335,7 @@ sub collect {
}
}
-sub write {
+sub write_master {
my ($self, $filename) = @_;
$filename ||= $self->{'default_filename'};
@@ -344,14 +346,15 @@ sub write {
}
open(F, ">$filename") or die("can't write to $filename");
- for my $c (sort keys %{$self->{'ballots'}}) {
- printf F "--------- confirmation %04x ---------\n", $c;
+ for my $c (sort { $a <=> $b } map { int $_ } keys %{$self->{'ballots'}}) {
+ my $confid = sprintf("%08x",$c);
+ printf F "--------- confirmation %s ---------\n", $confid;
print F $self->{'ballots'}{$c}->to_s
}
close F;
}
-sub read {
+sub read_master {
my ($self, $filename) = @_;
my ($election, $entries) = $self->{'election'};
@@ -362,7 +365,7 @@ sub read {
{ local $/ = undef; $entries = <F>; }
for my $e (split /^--------- confirmation /m, $entries) {
next unless $e; # skip the first zero-length record
- unless ($e =~ /^([[:xdigit:]]{4}) ---------\n(.*)$/s) {
+ unless ($e =~ /^([[:xdigit:]]{4,12}) ---------\n(.*)$/s) {
die "error parsing entry:\n$e";
}
my ($c, $s, $b) = ($1, $2, Ballot->new($election));
@@ -371,6 +374,24 @@ sub read {
}
}
+sub write_casting_voters {
+ my ($self, $filename) = @_;
+
+ $filename ||= $self->{'default_filename'};
+ $self->{'filename'} = $filename;
+
+ if (-f $filename) {
+ die "$filename already exists; please remove it first";
+ }
+
+ open(F, ">$filename") or die("can't write to $filename");
+ for my $v (sort keys %{$self->{'casting_voters'}}) {
+ printf F "%s\n", $v;
+ }
+ close F;
+}
+
+
sub generate_candidates {
my ($self) = @_;
my ($B, @C, $s);
diff --git a/countify b/countify
index 13618a4..cf31d69 100755
--- a/countify
+++ b/countify
@@ -19,9 +19,13 @@ BEGIN {
push @INC, $dirname;
}
-use POSIX;
+use Cwd qw(abs_path);
+use File::Basename;
+use File::Spec::Functions;
use Getopt::Long;
use List::Util;
+use POSIX;
+
use Votify 'official';
use strict;
@@ -94,12 +98,15 @@ if ($opt{'collect'}) {
$master->collect($vl->voters);
for my $o ($ol->officials) {
my ($uid, $home) = (getpwnam $o)[2,7];
- mkdir "$home/results-$election";
- $master->write("$home/results-$election/master-$election");
- $vl->write("$home/results-$election/confs-$election");
+ $home = "/home/$o" unless defined $home;
+ mkdir catfile("$home", "results-$election");
+ $master->write_master("$home/results-$election/master-$election");
+ $master->write_casting_voters("$home/results-$election/casting-voters-$election");
+ $vl->write_confs("$home/results-$election/confs-$election");
chown $uid, -1, "$home/results-$election",
"$home/results-$election/master-$election",
- "$home/results-$election/confs-$election";
+ "$home/results-$election/confs-$election",
+ "$home/results-$election/casting-voters-$election";
}
exit 0;
}
@@ -107,7 +114,7 @@ if ($opt{'collect'}) {
if ($opt{'rank'}) {
my ($master) = MasterBallot->new($election, $vl);
my (@candidates, @winner, @ranked, @ranks);
- $master->read("$ENV{HOME}/results-$election/master-$election");
+ $master->read_master("$ENV{HOME}/results-$election/master-$election");
$master->generate_candidates();
@candidates = sort keys %{$master->{'candidates'}};