#!/usr/bin/perl -w # $Id: countify,v 1.3 2005/05/16 18:10:46 agriffis Exp $ # # Copyright 2005-2015 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # # countify: collect, tabulate and announce ballot results # BEGIN { my $dirname; if(-f '/etc/elections/Votify.pm') { $dirname = '/etc/elections'; } else { use Cwd qw(abs_path); use File::Basename qw(dirname); $dirname = dirname(abs_path(__FILE__)); } push @INC, $dirname; } 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; ###################################################################### # Global vars ###################################################################### (my $zero = $0) =~ s,.*/,,; (my $version = $Votify::version) =~ s/.*?(\d.*\d).*/$zero version $1\n/; my %opt; # Collect the open elections my (%open_elections, $usage_elections); %open_elections = Votify::get_open_elections_hash(); if (scalar keys %open_elections) { $usage_elections = join("\n ", keys %open_elections); } else { $usage_elections = "(no elections currently open)"; } # rest of usage my $usage = < where is one of: --collect Collect the submitted ballots from home directories --rank Show ranking based on master ballot --help Show this help message --version Show version information and is one of the elections currently in-progress. The following elections are currently open: $usage_elections EOT ###################################################################### # Main ###################################################################### package main; # Make sure umask is secure before we do anything umask 077; # Parse the options on the cmdline. Put the short versions first in # each optionstring so that the hash keys are created using the short # versions. For example, use 'q|qar', not 'qar|q'. my ($result) = GetOptions( \%opt, 'collect', # collect the submitted ballots from home directories 'rank', # show the ranking based on a master ballot 'help', # help message 'version', # version information ); if ($opt{'help'} or not %opt) { print STDERR $usage; exit 0 } if ($opt{'version'}) { print STDERR $version; exit 0 } die "$zero: only one command allowed; use --help for help\n" if 1 < keys %opt; die "$zero: election required; use --help for help\n" unless @ARGV == 1; my ($election) = $ARGV[0]; my ($vl) = VoterList->new($election); if ($opt{'collect'}) { my ($ol) = OfficialList->new($election); my ($master) = MasterBallot->new($election, $vl); $master->collect($vl->voters); for my $o ($ol->officials) { my ($uid, $home) = (getpwnam $o)[2,7]; $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/casting-voters-$election"; } exit 0; } if ($opt{'rank'}) { my ($master) = MasterBallot->new($election, $vl); my (@candidates, @winner, @ranked, @ranks); $master->read_master("$ENV{HOME}/results-$election/master-$election"); $master->generate_candidates(); @candidates = sort keys %{$master->{'candidates'}}; while (1) { $master->tabulate(); # this is a hack :-( #print "\n"; for my $r (@ranked) { #print "$r is already ranked\n"; for my $c (@candidates) { $master->{'table'}{"$r+$c"} = -1; } $master->{'table'}{"$r+$r"} = '+++'; } # now display the table print "\n"; $master->display_table(); @winner = $master->cssd(); if (@winner == @candidates) { print "\n*** No additional winners to add to the list ***\n"; last; } push @ranks, [ @winner ]; push @ranked, @winner; if (@ranked == @candidates) { print "\n*** Finished ranking candidates ***\n"; last; } print "\n*** Running another pass to find the next winners... ***\n"; } print "\nFinal ranked list:\n"; print map "@$_\n", @ranks; } __END__ # vim:sw=4 et