X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=appendix-a6.git;a=blobdiff_plain;f=stv;h=3c6160e979f27ffa7f026ed59d20a4b2dabf2710;hp=03f16d8d0e418d2488e30a4011f1e92b9a6342b0;hb=5aadf4171505c30873eb9c1cc0deeaa752f095be;hpb=8a14c3d1ae526accda2146e15fc99f98c1b94548 diff --git a/stv b/stv index 03f16d8..3c6160e 100755 --- a/stv +++ b/stv @@ -3,6 +3,19 @@ # Does STV according to # http://www.rosenstiel.co.uk/stvrules/av/index.htm +# Usage: +# ./stv [TIEBREAK ...] PLACES [INPUT-FILES ...] +# +# PLACES is the number of seats to be filled +# +# INPUT-FILES are in the format: +# VOTER PQRST +# where P, Q, R, etc. are candidates. Candidates +# must be single letters. +# +# Each TIEBREAK is +# P,Q,... + use strict; use utf8; use autodie; @@ -20,6 +33,25 @@ use List::MoreUtils qw(nsort_by); our $stage=0; our @allvotes; +our %tiebreak; # $tiebreak{ winningcand }{ losingcand } = 1 + +while (@ARGV && $ARGV[0] =~ m/[<>]/) { + my ($losers, $winners) = ($? eq '<' ? ($`, $') : ($', $`)); + my @losers = sort split /\,/, $losers; + my @winners = sort split /\,/, $winners; + die "@losers @winners" if @losers>1 && @winners>1; + my @all = sort @losers, @winners; + my $record = sub { + my ($how, $howers) = @_; + return unless @$howers == 1; + die "@all $how" if defined $tiebreak{$how}{"@all"}; + $tiebreak{$how}{"@all"} = $howers->[0]; + }; + $record->('winner', \@winners); + $record->('loser', \@losers); + shift @ARGV; +} + our $places = shift @ARGV; die unless $places eq ($places + 0); @@ -134,7 +166,17 @@ sub historically_prefer ($@) { $numequal++; } - die 'random choice unimplemented' if $numequal > 1; + if ($numequal > 1) { + my $how = $signum > 0 ? 'winner' : 'loser'; + my @all = sort map { $_->{Cand} } @choices[ 0 .. $numequal-1 ]; + my $hower = $tiebreak{$how}{"@all"}; + if (defined $hower) { + printf "%7.7s %10s !!!!!!!!!!\n", "TIE".(uc $how), $hower; + return grep { $_->{Cand} eq $hower } @choices; + } + die "need tie break for $how between @all\n"; + } + return $choices[0]; } @@ -369,4 +411,14 @@ for (;;) { push @unsorted, @$votes; } +open VL, ">.stv.votes" or die $!; +foreach my $vote (@allvotes) { + print VL "----------------------------------------\n"; + print VL "voter $vote->{Voter}\n"; + print VL "prefs ". (join " ", @{ $vote->{Prefs} }). "\n"; + print VL $_, "\n" foreach @{ $vote->{Log} }; +} +print VL "========================================\n"; +close VL; + print "done.\n";