diff options
author | Jorge Manuel B. S. Vicetto (jmbsvicetto) <jmbsvicetto@gentoo.org> | 2013-06-28 12:49:19 +0000 |
---|---|---|
committer | Jorge Manuel B. S. Vicetto (jmbsvicetto) <jmbsvicetto@gentoo.org> | 2013-06-28 12:49:19 +0000 |
commit | 76c33523cfa735aa70a42a3913a4878db4fa57af (patch) | |
tree | 46505aba1825c148345e9defe4fccac49f5d2353 | |
parent | Add ciaranm's script to generate vote distribution maps for an election. (diff) | |
download | elections-76c33523cfa735aa70a42a3913a4878db4fa57af.tar.gz elections-76c33523cfa735aa70a42a3913a4878db4fa57af.tar.bz2 elections-76c33523cfa735aa70a42a3913a4878db4fa57af.zip |
Initial commit for the council-201306 and trustees-201306 elections.
l--------- | council-201306/Votify.pm | 1 | ||||
-rw-r--r-- | council-201306/ballot-council-201306 | 1 | ||||
-rw-r--r-- | council-201306/election-details | 6 | ||||
-rw-r--r-- | council-201306/get-devs-list | 2 | ||||
-rw-r--r-- | council-201306/officials-council-201306 | 5 | ||||
-rw-r--r-- | council-201306/voters-council-201306 | 239 | ||||
-rw-r--r-- | trustees-201306/Votify.pm | 684 | ||||
-rw-r--r-- | trustees-201306/ballot-trustees-201306 | 0 | ||||
-rw-r--r-- | trustees-201306/election-details | 7 | ||||
-rw-r--r-- | trustees-201306/officials-trustees-201306 | 4 |
10 files changed, 949 insertions, 0 deletions
diff --git a/council-201306/Votify.pm b/council-201306/Votify.pm new file mode 120000 index 0000000..a6f4461 --- /dev/null +++ b/council-201306/Votify.pm @@ -0,0 +1 @@ +../Votify.pm
\ No newline at end of file diff --git a/council-201306/ballot-council-201306 b/council-201306/ballot-council-201306 new file mode 100644 index 0000000..e8d662b --- /dev/null +++ b/council-201306/ballot-council-201306 @@ -0,0 +1 @@ +_reopen_nominations diff --git a/council-201306/election-details b/council-201306/election-details new file mode 100644 index 0000000..d7b896a --- /dev/null +++ b/council-201306/election-details @@ -0,0 +1,6 @@ +name: council-201306 +startDate: 2013-06-30 00:00:00 UTC +endDate: 2013-07-14 00:00:01 UTC +officials: antarus, jmbsvicetto, neddyseagoon, robbat2, tampakrap +voters: http://www.gentoo.org/proj/en/elections/council/2013/voters-council-201306.txt +ballot: http://www.gentoo.org/proj/en/elections/council/2013/ballot-council-201306.txt diff --git a/council-201306/get-devs-list b/council-201306/get-devs-list new file mode 100644 index 0000000..ce27f5c --- /dev/null +++ b/council-201306/get-devs-list @@ -0,0 +1,2 @@ +ENAME=$(awk '/^name:/{print $2}' election-details) +ldapsearch '(&(objectClass=gentooDev)(gentooStatus=active)(!(gentooAccess=infra-system.group)))' -Z uid -LLL -S uid | awk '/^uid:/ {print $2}' >${ENAME}-devs-list diff --git a/council-201306/officials-council-201306 b/council-201306/officials-council-201306 new file mode 100644 index 0000000..f5ce904 --- /dev/null +++ b/council-201306/officials-council-201306 @@ -0,0 +1,5 @@ +antarus +jmbsvicetto +neddyseagoon +robbat2 +tampakrap diff --git a/council-201306/voters-council-201306 b/council-201306/voters-council-201306 new file mode 100644 index 0000000..947a54f --- /dev/null +++ b/council-201306/voters-council-201306 @@ -0,0 +1,239 @@ +a3li +aballier +abcd +ackle +agaffney +ago +aidecoe +alexxy +alonbl +anarchy +angelos +antarus +araujo +armin76 +axs +betelgeuse +bicatali +billie +binki +blackace +blueboar +blueness +c1pher +calchan +cardoe +caster +cedk +chainsaw +chiguire +chithanh +chutzpah +constanze +craig +creffett +d2_racing +dabbott +dagger +dang +darkside +dastergon +dberkholz +deathwing00 +desultory +dev-zero +dilfridge +dirtyepic +djay +djc +dolsen +earthwings +elvanor +eras +eva +fauli +ferringb +flameeyes +flammie +floppym +ford_prefect +fordfrog +fox +fuzzyray +gengor +george +gienah +gmsoft +graaff +gregkh +grobian +grozin +gurligebis +halcy0n +hanno +hasufell +hattya +haubi +hd_brummy +heroxbd +hkbst +hollow +hparker +hwoarang +i92guboj +idella4 +idl0r +ikelos +iksaif +isaiah +jaervosz +jbartosik +jdhore +je_fro +jer +jkt +jlec +jmbsvicetto +jmorgan +john_r_graham +johu +joker +josejx +jsbronder +kallamej +ken69267 +kensington +keri +kernelsensei +keytoaster +kingtaco +klausman +klieber +klondike +kumba +lack +leio +lejonet +lh +lordvan +lu_zero +lxnay +mabi +maekke +maksbotan +marienz +matsl +matsuu +mattm +mattst88 +mduft +mgorny +miknix +miska +moult +mpagano +mr_bones_ +mschiff +naota +nathanzachary +nativemad +neddyseagoon +nerdboy +neurogeek +nightmorph +nimiux +nirbheek +nixnut +nixphoeni +olemarkus +ottxor +pacho +patrick +pauldv +pchrist +pebenito +peper +pesa +phajdan.jr +phosphan +pilla +pinkbyte +pjp +polynomial-c +prometheanfire +psomas +pva +pvdabeel +qiaomuf +qnikst +quantumsummers +r0bertz +radhermit +rafaelmartins +rajiv +ramereth +rane +ranger +reavertm +remi +rich0 +robbat2 +ryao +s4t4n +sbriesen +scarabeus +sera +serkan +slis +slyfox +sochotnicky +solar +sping +spiros +ssuominen +steev +suka +swegener +swift +tampakrap +tester +tetromino +tgurr +the_paya +thev00d00 +think4urs11 +timebandit +titanofold +tomjbe +tomk +tomka +tommy +tomwij +tove +trapni +tristan +tupone +ulm +ultrabug +underling +vadimk +vapier +vikraman +vincent +vostorga +voyageur +weaver +williamh +wired +wormo +wschlich +xarthisius +xmw +yac +yngwin +zerochaos +zlogene +zmedico +zorry +zx2c4 +zzam diff --git a/trustees-201306/Votify.pm b/trustees-201306/Votify.pm new file mode 100644 index 0000000..c99685d --- /dev/null +++ b/trustees-201306/Votify.pm @@ -0,0 +1,684 @@ +# $Id: Votify.pm,v 1.5 2005/05/16 23:58:09 agriffis Exp $ +# +# Copyright 2005 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# +# votify.pm: common classes for votify and countify +# + +package Votify; + +use POSIX; +use List::Util; +use strict; + +our ($datadir) = '/etc/elections/current'; +(our $zero = $0) =~ s,.*/,,; + +sub import { + my ($class, $mode) = @_; + $Votify::mode = $mode; +} + +###################################################################### +# OfficialList +###################################################################### + +package OfficialList; + +sub new { + my ($class, $election) = @_; + my ($self) = { + election => $election, + officials => [], + }; + + # no point in waiting to load + open(F, "<$Votify::datadir/officials-$election") + or die("failed to open officials file"); + chomp(@{$self->{'officials'}} = <F>); + close(F); + + bless $self, $class; + return $self; +} + +sub officials { + my ($self) = @_; + @{$self->{'officials'}}; +} + +###################################################################### +# VoterList +###################################################################### + +package VoterList; + +sub new { + my ($class, $election) = @_; + my (@voterlist, $r); + my ($self) = { + election => $election, + default_filename => "$Votify::datadir/confs-$election", + filename => '', + voters => {}, # confnum => voter + confs => {}, # voter => confnum + }; + + # no point in waiting to load + open(F, "<$Votify::datadir/voters-$election") + or die("failed to open voters file"); + chomp(@voterlist = <F>); + close(F); + + # assign confirmation numbers randomly + for my $v (@voterlist) { + do { $r = int rand 0xffff } while exists $self->{'voters'}{$r}; + $self->{'voters'}{$r} = $v; + $self->{'confs'}{$v} = $r; + } + + unless (keys %{$self->{'voters'}} == keys %{$self->{'confs'}}) { + die("discrepancy deteced in VoterList"); + } + + bless $self, $class; + return $self; +} + +sub confs { + my ($self) = @_; + sort keys %{$self->{'voters'}}; +} + +sub voters { + my ($self) = @_; + sort keys %{$self->{'confs'}}; +} + +sub getvoter { + my ($self, $conf) = @_; + return $self->{'voters'}{$conf}; +} + +sub getconf { + my ($self, $voter) = @_; + return $self->{'confs'}{$voter}; +} + +sub write { + 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 $c ($self->confs) { + printf F "%04x %s\n", $c, $self->getvoter($c); + } + close F; +} + +###################################################################### +# MasterBallot +###################################################################### + +package MasterBallot; + +use Data::Dumper; + +sub new { + my ($class, $election, $vl) = @_; + my ($self) = { + election => $election, + default_filename => "$Votify::datadir/master-$election", + filename => '', + voterlist => $vl, + ballots => {}, # indexed by conf num + candidates => undef, # indexed by long name + table => undef, # indexed by row+column + }; + + bless $self, $class; + return $self; +} + +sub collect { + my ($self, @voters) = @_; + my ($c, $v, $home, @pwentry); + + for my $v (@voters) { + unless (defined ($c = $self->{'voterlist'}->getconf($v))) { + die "$v does not correspond to any confirmation number"; + } + + @pwentry = getpwnam($v); + if(@pwentry) { + $home = $pwentry[7]; + } else { + print STDERR "Warning: Assuming /home/$v/ for unknown user: $v\n"; + $home = sprintf '/home/%s/',$v; + } + + unless (-d $home) { + print STDERR "Warning: no directory: $home\n"; + next; + } + + if (-f "$home/.ballot-$self->{election}-submitted") { + my ($b) = Ballot->new($self->{'election'}); + $b->read("$home/.ballot-$self->{election}-submitted"); + if ($b->verify) { + print STDERR "Errors found in ballot: $v\n"; + next; + } + $self->{'ballots'}{$c} = $b; + } + elsif (-f "$home/.ballot-$self->{election}") { + print STDERR "Warning: $v did not submit their ballot\n"; + } + } +} + +sub write { + 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 $c (sort keys %{$self->{'ballots'}}) { + printf F "--------- confirmation %04x ---------\n", $c; + print F $self->{'ballots'}{$c}->to_s + } + close F; +} + +sub read { + my ($self, $filename) = @_; + my ($election, $entries) = $self->{'election'}; + + $filename ||= $self->{'default_filename'}; + $self->{'filename'} = $filename; + + open(F, "<$filename") or die("can't read $filename"); + { 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) { + die "error parsing entry:\n$e"; + } + my ($c, $s, $b) = ($1, $2, Ballot->new($election)); + $b->from_s($s); + $self->{'ballots'}{hex($c)} = $b; + } +} + +sub generate_candidates { + my ($self) = @_; + my ($B, @C, $s); + + # nb: would need to scan all the ballots to support write-ins + $B = Ballot->new($self->{'election'}); + $B->populate; + @C = sort map $_->[0], @{$B->choices}; + for my $c (@C) { + $s = $c; # in case $c is shorter than 5 chars + for (my $i=5; $i<=length($c); $i++) { + $s = substr $c, 0, $i; + print join(" ", grep(/^$s/, @C)), "\n"; + last unless grep(/^$s/, @C) > 1; + } + $self->{'candidates'}{$c} = $s; + } +} + +sub tabulate { + my ($self) = @_; + my (@candidates); # full candidate list + my (%table); # resulting table, row.colum where row defeats column + $self->{'table'} = \%table; + + $self->generate_candidates unless $self->{'candidates'}; + @candidates = keys %{$self->{'candidates'}}; + for my $c1 (@candidates) { + for my $c2 (@candidates) { + $table{"$c1+$c2"} = 0; + } + $table{"$c1+$c1"} = '***'; + } + + # generate the table first; + # walk through the ballots, tallying the rankings expressed by each ballot + for my $b (values %{$self->{'ballots'}}) { + my (@choices, %ranks); + + #print "looking at ballot:\n", $b->to_s, "\n"; + + # first determine the ranking of each candidate. default ranking is + # scalar @candidates. + @choices = @{$b->choices}; + @ranks{@candidates} = (scalar @candidates) x @candidates; + #print "ranks before determining:\n", Dumper(\%ranks); + for (my $i = 0; $i < @choices; $i++) { + @ranks{@{$choices[$i]}} = ($i) x @{$choices[$i]}; + } + #print "ranks after determining:\n", Dumper(\%ranks); + + # second add the results of all the pairwise races into our table + for my $c1 (@candidates) { + for my $c2 (@candidates) { + next if $c1 eq $c2; + $table{"$c1+$c2"}++ if $ranks{$c1} < $ranks{$c2}; + } + } + #print "table after adding:\n"; + #$self->display_table; + } +} + +sub display_table { + my ($self) = @_; + my (@longnames, @shortnames); + my ($minlen, $maxlen, $formatstr) = (0, 4, ''); + + $self->generate_candidates unless $self->{'candidates'}; + @longnames = sort keys %{$self->{'candidates'}}; + @shortnames = sort values %{$self->{'candidates'}}; + $minlen = length scalar keys %{$self->{'ballots'}}; + $minlen = 5 if $minlen < 5; + + # build the format string + for my $s (@shortnames) { + if (length($s) > $minlen) { + $formatstr .= " %" . length($s) . "s"; + } else { + $formatstr .= " %${minlen}s"; + } + } + map { $maxlen = length($_) if length($_) > $maxlen } @longnames; + + # prepend the row header; append newline + $formatstr = "%${maxlen}s" . $formatstr . "\n"; + + # column headers + printf $formatstr, '', @shortnames; + + # rows + for my $l (@longnames) { + printf $formatstr, $l, @{$self->{'table'}}{map "$l+$_", @longnames}; + } +} + +# utility for cssd +sub defeats { + my ($self, $o1, $o2) = @_; + return 0 if $o1 eq $o2; + $self->{'table'}{"$o1+$o2"} > $self->{'table'}{"$o2+$o1"}; +} + +# utility for cssd +sub is_weaker_defeat { + my ($self, $A, $X, $B, $Y) = @_; + die unless $self->defeats($A, $X); + die unless $self->defeats($B, $Y); + return ( + $self->{'table'}{"$A+$X"} < $self->{'table'}{"$B+$Y"} or + ( + $self->{'table'}{"$A+$X"} == $self->{'table'}{"$B+$Y"} and + $self->{'table'}{"$X+$A"} > $self->{'table'}{"$Y+$B"} + ) + ); +} + +sub cssd { + my ($self) = @_; + my (@candidates); + + @candidates = sort keys %{$self->{'candidates'}}; + + while (1) { + my (%transitive_defeats); + my (@active, @plist); + + ###################################################################### + # 5. From the list of [undropped] pairwise defeats, we generate a + # set of transitive defeats. + # 1. An option A transitively defeats an option C if A + # defeats C or if there is some other option B where A + # defeats B AND B transitively defeats C. + for my $o1 (@candidates) { + for my $o2 (@candidates) { + $transitive_defeats{"$o1+$o2"} = 1 if $self->defeats($o1, $o2); + } + } + for my $i (@candidates) { + for my $j (@candidates) { + for my $k (@candidates) { + if (exists $transitive_defeats{"$j+$i"} and + exists $transitive_defeats{"$i+$k"}) + { + $transitive_defeats{"$j+$k"} = 1; + } + } + } + } + + ###################################################################### + # 6. We construct the Schwartz set from the set of transitive + # defeats. + # 1. An option A is in the Schwartz set if for all options B, + # either A transitively defeats B, or B does not + # transitively defeat A. + print "\n"; + A: for my $A (@candidates) { + for my $B (@candidates) { + next if $transitive_defeats{"$A+$B"} or not $transitive_defeats{"$B+$A"}; + # countify marks entries +++ instead of *** when they've already + # been ranked. + if ($self->{'table'}{"$A+$A"} eq '***') { + print "option $A is eliminated ($B trans-defeats $A, and $A does not trans-defeat $B)\n"; + } + next A; + } + push @active, $A; + } + print "the Schwartz set is {", join(", ", @active), "}\n"; + @candidates = @active; + + ###################################################################### + # 7. If there are defeats between options in the Schwartz set, we + # drop the weakest such defeats from the list of pairwise + # defeats, and return to step 5. + # 1. A defeat (A,X) is weaker than a defeat (B,Y) if V(A,X) + # is less than V(B,Y). Also, (A,X) is weaker than (B,Y) if + # V(A,X) is equal to V(B,Y) and V(X,A) is greater than V + # (Y,B). + # 2. A weakest defeat is a defeat that has no other defeat + # weaker than it. There may be more than one such defeat. + for my $o1 (@candidates) { + for my $o2 (@candidates) { + push @plist, [ $o1, $o2 ] if $self->defeats($o1, $o2); + } + } + last unless @plist; + @plist = sort { + return -1 if $self->is_weaker_defeat(@$a, @$b); + return +1 if $self->is_weaker_defeat(@$b, @$a); + return 0; + } @plist; + for my $dx (@plist) { + my ($o1, $o2) = @$dx; + print("$o1+$o2 ", + $self->{'table'}{"$o1+$o2"}, " $o2+$o1 ", + $self->{'table'}{"$o2+$o1"}, "\n"); + } + my ($o1, $o2) = @{$plist[0]}; + $self->{'table'}{"$o1+$o2"} = 0; + $self->{'table'}{"$o2+$o1"} = 0; + } + + ###################################################################### + # 8. If there are no defeats within the Schwartz set, then the + # winner is chosen from the options in the Schwartz set. If + # there is only one such option, it is the winner. If there + # are multiple options, the elector with the casting vote + # chooses which of those options wins. + print "\n"; + if (@candidates > 1) { + print "result: tie between options ", join(", ", @candidates), "\n"; + } else { + print "result: option @candidates wins\n"; + } + + return @candidates; +} + +###################################################################### +# Ballot +###################################################################### + +package Ballot; + +sub new { + my ($class, $election) = @_; + my ($self) = { + election => $election, + filename => '', + default_filename => $ENV{'HOME'}."/.ballot-$election", + choices => [], + }; + + # Bless me, I'm a ballot! + bless $self, $class; + return $self; +} + +sub from_s { + my ($self, $s) = @_; + my (@choices); + + for (split "\n", $s) { + s/#.*//; + next unless /\S/; + push @choices, [ split(' ', $_) ]; + } + die("No data in string") unless @choices; + + $self->{'choices'} = \@choices; +} + +sub read { + my ($self, $filename) = @_; + + $filename ||= $self->{'default_filename'}; + $self->{'filename'} = $filename; + + # Load the data file + open(F, "<$filename") or die("couldn't open $filename"); + { local $/ = undef; $self->from_s(<F>); } + close(F); +} + +sub populate { + my ($self) = @_; + $self->read("$Votify::datadir/ballot-$self->{election}"); + @{$self->{'choices'}} = List::Util::shuffle(@{$self->{'choices'}}); +} + +sub choices { + my ($self) = @_; + $self->{'choices'}; +} + +sub write { + my ($self, $filename) = @_; + + if ($Votify::mode ne 'user') { + die("we don't write ballots in official mode"); + } + + $filename ||= $self->{'default_filename'}; + $self->{'filename'} = $filename; + + # Don't ever overwrite a ballot + die("File already exists; please remove $filename\n") if -e $filename; + + # Write the user's ballot + open(F, ">$filename") or die "Failed writing $filename"; + print F <<EOT; +# This is a ballot for the $self->{election} election. +# Please rank your choices in order; first choice at the top and last choice at +# the bottom. You can put choices on the same line to indicate no preference +# between them. Any choices you omit from this file are implicitly added at the +# end. +# +# When you're finished editing this, the next step is to verify your ballot +# with: +# +# $Votify::zero --verify $self->{election} +# +# When that passes and you're satisfied, the final step is to submit your vote: +# +# $Votify::zero --submit $self->{election} +# + +EOT + for (@{$self->{'choices'}}) { print F "@$_\n"; } + close(F); +} + +sub verify { + my ($self) = @_; + my (%h, $master, %mh); + my (@dups, @missing, @extra); + my ($errors_found); + + # Load %h from the user's ballot + for my $line (@{$self->{'choices'}}) { + for my $entry (@$line) { + $h{$entry}++; + } + } + + # Load the master ballot into another hash and compare them. + # The master ballots always do one entry per line, making this a little + # easier. + $master = Ballot->new($self->{'election'}); + $master->populate; + %mh = map(($_->[0] => 1), @{$master->{'choices'}}); + + # Check for extra entries (write-ins should be supported in the future) + for (keys %h) { + push @extra, $_ unless exists $mh{$_}; + } + + # Check for duplicate entries + @dups = grep { $h{$_} > 1 } keys %h; + + # Check for missing entries (not necessarily an error) + for (keys %mh) { + push @missing, $_ unless exists $h{$_}; + } + + # Report errors and warnings + if (@extra) { + if ($Votify::mode eq 'user') { + print <<EOT; +Your ballot has some extra entries that are not part of this election. Sorry, +but write-ins are not (yet) supported. Please remove these from your ballot: + +EOT + print map "\t$_\n", @extra; + print "\n"; + } + $errors_found++; + } + if (@dups) { + if ($Votify::mode eq 'user') { + print <<EOT; +Your ballot has some duplicate entries. Please resolve these to a single entry +to avoid ambiguities: + +EOT + print map "\t$_\n", @dups; + print "\n"; + } + $errors_found++; + } + if (@{$self->{'choices'}} == 0) { + if ($Votify::mode eq 'user') { + print <<EOT; +Your ballot doesn't contain any entries. You can start over by first removing +the existing ballot, then using --new to generate a new ballot. See --help for +more information. + +EOT + } + $errors_found++; + } + elsif (@missing and $Votify::mode eq 'user') { + print <<EOT; +Your ballot is missing some entries. This is not an error, but note that these +will be implied as a final line, with no preference between them, like this: + +EOT + print "\t", join(" ", @missing), "\n"; + print "\n"; + } + if ($Votify::mode eq 'user' and !$errors_found and + @{$self->{'choices'}} == 1 and + scalar(keys %h) == scalar(keys %mh)) + { + print <<EOT; +Your ballot contains all the candidates on a single line! This means you have +no preference between the candidates. This is not an error, but note that this +is a meaningless ballot that will have no effect on the election. + +EOT + } + + # Stop if there were errors + if ($Votify::mode eq 'user' and $errors_found) { + print("There were errors found in your ballot.\n"); + die("Please correct them and try again.\n\n"); + } + return $errors_found; +} + +sub to_s { + my ($self) = @_; + join '', map "@$_\n", @{$self->{'choices'}}; +} + +1; + +__END__ + +$Log: Votify.pm,v $ +Revision 1.5 2005/05/16 23:58:09 agriffis +change wording + +Revision 1.4 2005/05/16 18:40:07 agriffis +fix shortname calculation + +Revision 1.3 2005/05/16 18:10:46 agriffis +ranking works completely now, even if it needs badly to be refactored + +Revision 1.2 2005/05/16 04:03:46 agriffis +add first pass at countify --rank + + +__END__ + +$Log: Votify.pm,v $ +Revision 1.5 2005/05/16 23:58:09 agriffis +change wording + +Revision 1.4 2005/05/16 18:40:07 agriffis +fix shortname calculation + +Revision 1.3 2005/05/16 18:10:46 agriffis +ranking works completely now, even if it needs badly to be refactored + +Revision 1.2 2005/05/16 04:03:46 agriffis +add first pass at countify --rank + +Revision 1.3 2005/05/09 23:12:02 agriffis +Add support for registered voters + +Revision 1.2 2005/05/05 23:03:46 agriffis +Fix indentation (and some output as well) + +Revision 1.1 2005/05/05 22:05:34 agriffis +first pass at Gentoo Foundation voting program + +# vim:sw=4 et diff --git a/trustees-201306/ballot-trustees-201306 b/trustees-201306/ballot-trustees-201306 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/trustees-201306/ballot-trustees-201306 diff --git a/trustees-201306/election-details b/trustees-201306/election-details new file mode 100644 index 0000000..2eb59cb --- /dev/null +++ b/trustees-201306/election-details @@ -0,0 +1,7 @@ +name: trustees-201306 +startDate: 2013-07-14 00:00:00 UTC +endDate: 2013-08-11 00:00:01 UTC +officials: jmbsvicetto, neddyseagoon, robbat2, tampakrap +voters: http://www.gentoo.org/proj/en/elections/trustees/2013/voters-trustees-201306.txt +ballot: http://www.gentoo.org/proj/en/elections/trustees/2013/ballot-trustees-201306.txt + diff --git a/trustees-201306/officials-trustees-201306 b/trustees-201306/officials-trustees-201306 new file mode 100644 index 0000000..38f9b76 --- /dev/null +++ b/trustees-201306/officials-trustees-201306 @@ -0,0 +1,4 @@ +jmbsvicetto +neddyseagoon +robbat2 +tampakrap |