#! /usr/bin/perl -w # Copyright (C) 2000-2002 Henrik Christian Grove # og Frank Damgaard # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA require POSIX; use strict; # Konstante værdier som det kan være interessant at ændre my $versionsnummer = "0.96"; my $aarstal = 2002; my $antal_pladser = 6; my $antal_suppleanter = 2; my $prioritetsniveauer = 5; # ofte antal bestyrelsespladser (excl suppleanter) my $mypath="."; my $stemmefil="$mypath/stemmer.txt"; my $kandidaterfil="$mypath/kandidater.txt"; # Variabelerklæringer my $antal_kandidater = 0; my @kandidat; #my @stemmer; my $afgivne_stemmer = 0; my $fordelingstal = 0; my @nyt; my @felt; my $trouble; # Indlæs liste med kandidaternes navne fra filen $kandidaterfil # # Filformat: Ét navn pr. linie, mellemrum i starten og slutningen af # linien fjernes # sub indl_kandidater { open(KAND, $kandidaterfil) or die "Kan ikke åbne $kandidaterfil: $!"; while (){ chomp; # if ( $_ && !( $_ =~ /^[\s]+$/ ) ) { if (/^\s*(\S.*?)\s*$/) { $antal_kandidater++; $kandidat[$antal_kandidater]{"navn"} = $1; } } close(KAND); } #sub indl_stemmer_1 { # my @arr; # my $cnt=0; # my $lncnt=0; # my $snr; # my $sprior; # my $serror; # for ($snr=0; $snr<$antal_kandidater; $snr++) { # for ($sprior=1; $sprior<=$prioritetsniveauer; $sprior++) { # $stemmer[$sprior+$snr*$prioritetsniveauer]=0; # } # } # # open(STEM, $stemmefil) or die "Can't open $stemmefil: $!"; # while (){ # $lncnt++; # $serror=0; # chomp; # $snr=$_; # $snr =~ s/^.*;\s*// ; # @arr= split(/\s/,$snr) ; # if ($#arr>0) { # for ($cnt=0; $cnt<=$#arr ; $cnt++ ) { # $snr = $arr[$cnt]; # $sprior = $snr; # $snr =~ s/:.*//; # $sprior =~ s/^.*://; # if ( $snr > 0 && $snr<=$antal_kandidater # && $sprior>=0 && $sprior<=$prioritetsniveauer ) { # $stemmer[$sprior+($snr-1)*$prioritetsniveauer] += 1; # } else { # $serror++; # } # } # if ($serror>0) { # print "*** $serror fejl i stemmeseddel linie $lncnt :\n"; # print "*** [",$_,"]\n"; # } # } # } # close(STEM); # for ($snr=0; $snr<$antal_kandidater; $snr++) { # printf "%3d: %-22s",$snr+1,$kandidat[$snr+1]{'navn'}; # for ($sprior=1; $sprior<=$prioritetsniveauer; $sprior++) { # printf "%4d",$stemmer[$sprior+$snr*$prioritetsniveauer]; # } # print "\n"; # } #} # Indlæs de afgivne stemmer fra filen $stemmefil # # Det her må Frank tjekke... # Filformat: En linie pr. stemmeseddel. # Linieformat (regex): sid[^;]*;\s*(kand:prio\s+)*\s* # # Hvor sid er et unikt id-nummer (bruges til at tjekke for dubletter), # og kand:prio er nummeret på en kandidat og den stemmeprioritet der # er afgivet på kandidaten. sub indl_stemmer { my @arr; my $bak; my $sid; my %stemmeseddel; my %stemmelinie; my $linienr = 0; my $skand; my $sprio; my $serror=0; my $cnt; for ($skand=1; $skand<=$antal_kandidater; $skand++) { for ($sprio=1; $sprio<=$prioritetsniveauer; $sprio++) { $kandidat[$skand]{"modtagne_stemmer$sprio"} = 0; } } open(STEM, $stemmefil) or die "Kan ikke åbne $stemmefil: $!"; while (){ $linienr++; chomp; $bak=$_; s/;.*\s*// ; @arr = split /\s/; $sid = $arr[0]; $sid = "$sid"; $_=$bak; s/^.*;\s*// ; if ( defined $stemmeseddel{$sid}) { printf "duplet gammel=[%s]\n",$stemmeseddel{$sid}; printf "%9s ny=[%s]\n",$sid,$_; } $stemmeseddel{$sid} = $_; $stemmelinie{$sid} = $linienr; } close(STEM); foreach $sid (keys %stemmeseddel) { @arr = split(/\s/,$stemmeseddel{$sid}) ; if ($#arr>0) { $afgivne_stemmer++; for ($cnt=0; $cnt<=$#arr ; $cnt++ ) { $skand = $arr[$cnt]; $sprio = $skand; $skand =~ s/:.*//; $sprio =~ s/^.*://; if ( $skand > 0 && $skand<=$antal_kandidater && $sprio>=0 && $sprio<=$prioritetsniveauer ) { # $stemmer[$sprio+($skand-1)*$prioritetsniveauer] += 1; $kandidat[$skand]{"modtagne_stemmer$sprio"}++; } else { $serror++; } } if ($serror>0) { print "*** $serror fejl i stemmeseddel linie $stemmelinie{$sid} :\n"; print "*** [",$_,"]\n"; } } } } my @colors; @colors[1..8] = (0xf0ff99,0xe0ffc0,0xfff099,0xd0ffa0, 0xf0e099,0xe0f099,0xe0d099,0xd0c099); # Lav HTML-fil med en side af resultatet # # Frank har tilføjet nogle baggrundsfarver til tabellen, desværre ikke # med CSS sub ud_html { my $nummer = shift(@_); my $i; my $j; my $bgcolor; my $bgcolortxt; my $valgtst; my $vprior; if ($nummer) { open(UDFIL,">res-$nummer.html"); } else { open(UDFIL,">endeligt-resultat.html"); } print UDFIL "\n", "\n", "\n", "Resultat af SSLUG's bestyrelsesvalg $aarstal"; if ($nummer) { print UDFIL " -- $nummer"; } print UDFIL "\n", "\n", "\n", " \n", "\n", "

Resultat af SSLUG\'s bestyrelsesvalg $aarstal

\n\n", "

Der er afgivet $afgivne_stemmer stemmer.
\n", "Fordelingstallet er $fordelingstal.

\n", "\n", ""; for($i=1; $i<=$prioritetsniveauer; $i++) { print UDFIL ""; } print UDFIL "\n"; $bgcolor=0xffffff; for($i=1; $i<=$antal_kandidater; $i++){ print UDFIL ""; # valgst & prior should be stored in the counting-part, but... # Hvilket de pudsigt nok også er (og hele tiden har været) # de findes i henholdsvis $kandidat[$i]{'stemmer'} # og $kandidat[$i]{'valgt'} $valgtst= $felt[$i][3]; if ( $valgtst =~ /\d+\.\d+/ ) { $vprior = $valgtst; $vprior =~ s/\.\d+//; $valgtst =~ s/\d+\.//; $bgcolor= $colors[$vprior]; #$bgcolor=0xfff088; } else { $vprior=0; $valgtst=0; } for($j=1; $j<= $prioritetsniveauer+3; $j++) { if ($j<3 || $vprior==0 || $j>$vprior+3 ) { $bgcolortxt=""; } else { $bgcolortxt=sprintf "bgcolor=\"#%06x\"",$bgcolor } if ($nyt[$i][$j]) { print UDFIL ""; } print UDFIL "\n"; if ($i==$antal_pladser) { print UDFIL ""; print UDFIL ""; print UDFIL "\n"; } if ($i==$antal_pladser+$antal_suppleanter) { print UDFIL ""; print UDFIL ""; print UDFIL "\n"; } } print UDFIL "
NavnValgt somStemmer$i
$felt[$i][$j] "; } else { print UDFIL "$felt[$i][$j] "; } print UDFIL "
 
 
\n\n"; if ($nummer) { print UDFIL "Næste side"; } if ($nummer>5) { print UDFIL "\nEndeligt resultat"; } print UDFIL "\n", "
\n", "

Genereret af valg.pl, version $versionsnummer
\n", "Copyright (C) 2000-2002 ", "Henrik Christian Grove ", "<grove\@sslug.dk>\n", "og Frank Damgaard ", "<frank\@sslug.dk>

\n", "\n", "\n"; close(UDFIL); } # ud_html # Sammenlign to kandidater for at afgøre hvem der bliver valgt først. sub smlign_kandidater { my $r; my $i; # print("$kandidat[$a]{'navn'} <=> $kandidat[$b]{'navn'}\n"); if ($kandidat[$a]{'valgt'} < $kandidat[$b]{'valgt'}) { return -1; } if ($kandidat[$b]{'valgt'} < $kandidat[$a]{'valgt'}) { return 1; } if ($kandidat[$a]{'stemmer'} > $kandidat[$b]{'stemmer'}) { return -1; } if ($kandidat[$b]{'stemmer'} > $kandidat[$a]{'stemmer'}) { return 1; } $r = 0; for ($i=1; ($i<=$prioritetsniveauer) && ($r==0); $i++) { if ($kandidat[$a]{"modtagne_stemmer$i"} > $kandidat[$b]{"modtagne_stemmer$i"}) { $r = -1; } if ($kandidat[$b]{"modtagne_stemmer$i"} > $kandidat[$a]{"modtagne_stemmer$i"}) { $r = 1; } } if ($kandidat[$a]{'magic'} < $kandidat[$b]{'magic'}) { $r = -1; } if ($kandidat[$b]{'magic'} < $kandidat[$a]{'magic'}) { $r = 1; } if ($r) { return $r; } print("Lodtrækning påkrævet mellem $kandidat[$a]{'navn'} og $kandidat[$b]{'navn'}\n"); $trouble = 1; return 0; } # smlign_kandidater # Lokalisér evt. behov for lodtrækninger og bed om et resultat af hver # af dem. sub traeklod { my $i; my $j; my $k; my $p; my $tjah; $i = 0; do { $tjah = 0; do { $i++; } until (($i==$antal_kandidater) || (($kandidat[$i]{'valgt'}==$kandidat[$i+1]{'valgt'}) && ($kandidat[$i]{'stemmer'}==$kandidat[$i+1]{'stemmer'}))); unless ($i==$antal_kandidater) { $tjah = 1; $j = $i; do { $j++; $p = 0; do { $p++; } while (($p<=$prioritetsniveauer) && ($kandidat[$i]{"modtagne_stemmer$p"} ==$kandidat[$j]{"modtagne_stemmer$p"})); if ($p<=$prioritetsniveauer) { $tjah = 0; } } while (($tjah) && ($kandidat[$i]{'valgt'}==$kandidat[$j+1]{'valgt'}) && ($kandidat[$i]{'stemmer'}==$kandidat[$j+1]{'stemmer'})); if ($tjah) { print "Træk lod mellem\n"; for ($k=$i; $k<=$j; $k++) { print " $kandidat[$k]{'navn'}\n"; } print "Indtast nu et tal for hver kandidat, lavest for vinderen af lodtrækningen.\n"; for ($k=$i; $k<=$j; $k++) { print "Indtast for $kandidat[$k]{'navn'}-> "; $kandidat[$k]{'magic'} = ; } } $i = $j; } } until ($i==$antal_kandidater); } # traeklod # Testdata - 10 kandidater, 5 prioriteter, 31 afgivne stemmer # Virkelige data skal indlæses #$antal_kandidater = 10; #$kandidat[1]{'navn'} = "Luke Skywalker"; #$kandidat[2]{'navn'} = "Prinsesse Leia"; #$kandidat[3]{'navn'} = "Han Solo"; #$kandidat[4]{'navn'} = "Chewbacca"; #$kandidat[5]{'navn'} = "Dronning Amidala"; #$kandidat[6]{'navn'} = "Obi-Wan Kenobi"; #$kandidat[7]{'navn'} = "Yoda"; #$kandidat[8]{'navn'} = "Jar-Jar Binks"; #$kandidat[9]{'navn'} = "C-3PO"; #$kandidat[10]{'navn'} = "R2-D2"; # #$afgivne_stemmer = 31; #@stemmer[1..50] = ( 1, 3, 3, 5, 5, #1 # 1, 6, 7, 4, 5, #2 # 0, 1, 2, 2, 4, #3 # 1, 0, 0, 0, 3, #4 # 3, 2, 2, 5, 2, #5 # 20, 5, 2, 1, 0, #6 # 1, 0, 3, 1, 2, #7 # 1,10, 9, 8, 3, #8 # 0, 2, 1, 2, 2, #9 # 3, 2, 2, 3, 2); #10 ## 31 31 31 31 28 # Testdata - slut ##### Her begynder programet ##### my $i; my $j; my $niveau; my @sorteret; my $side; &indl_kandidater; print "$antal_kandidater kandidater indlæst!\n"; &indl_stemmer; print "$afgivne_stemmer stemmer indlæst!\n"; for ($i=0; $i<$antal_kandidater; $i++) { # De to næste linier uddeler teststemmerne til kandidaterne # for ($j=1; $j<=$prioritetsniveauer; $j++) # { $kandidat[$i+1]{"modtagne_stemmer$j"} = $stemmer[$prioritetsniveauer*$i+$j]; } $kandidat[$i+1]{'valgt'} = $prioritetsniveauer+1; $kandidat[$i+1]{'stemmer'} = 0; $kandidat[$i+1]{'magic'} = 0; } $fordelingstal = POSIX::floor($afgivne_stemmer/($antal_pladser+1))+1; print "Fordelingstallet beregnet til $fordelingstal\n"; # Her opgøres resultatet for ($niveau=1; $niveau<=$prioritetsniveauer; $niveau++) { print STDERR "Opgør niveau $niveau...\n"; for ($i=1; $i<=$antal_kandidater; $i++) { if ($kandidat[$i]{'valgt'} == $prioritetsniveauer+1) { $kandidat[$i]{'stemmer'} += $kandidat[$i]{"modtagne_stemmer$niveau"}; } if (($kandidat[$i]{'stemmer'} >= $fordelingstal) && ($kandidat[$i]{'valgt'} == $prioritetsniveauer+1)) { $kandidat[$i]{'valgt'} = $niveau; } } } print("---------------------------------\n"); for ($i=1; $i<=$antal_kandidater; $i++) { printf("$kandidat[$i]{'navn'} $kandidat[$i]{'valgt'}.$kandidat[$i]{'stemmer'}\n"); } print("---------------------------------\n"); print "Sorterer kandidaterne...\n"; $trouble = 0; # Det her er lidt sjovt! # Vi lader som om vi bare vil sortere tallene fra 1 til $antal_kandidater, # men sammenligningsfunktionen sammenligner rent faktisk kandidaterne med de # det tilsvarende numre, så @sorteret kommer ikke til at se sorteret ud. @sorteret = sort smlign_kandidater ( 1..$antal_kandidater ); @kandidat[1..$antal_kandidater] = @kandidat[@sorteret]; if ($trouble) { &traeklod; # Tabellen er næsten sorteret, så måske kunne det være en fordel at # sortere @sorteret - kræver viden om Perls sort-funktion at afgøre print("---------------------------------\n"); print "Sorterer kandidaterne...\n"; @sorteret = sort smlign_kandidater ( 1..$antal_kandidater ); @kandidat[1..$antal_kandidater] = @kandidat[@sorteret]; } print("---------------------------------\n"); for ($i=1; $i<=$antal_kandidater; $i++) { printf("$kandidat[$i]{'navn'} $kandidat[$i]{'valgt'}.$kandidat[$i]{'stemmer'}\n"); } # Initialiser uddata-skemaet for ($i=1; $i<=$antal_kandidater; $i++) { $felt[$i][1] = " "; $felt[$i][2] = " "; $felt[$i][3] = 0; for ($j=4; $j<=$prioritetsniveauer+3; $j++) { $felt[$i][$j] = " "; } } $side = 1; &ud_html($side++); for ($niveau=1; $niveau<=$prioritetsniveauer; $niveau++) { for ($i=1; $i<=$antal_kandidater; $i++) { for ($j=1; $j<=$prioritetsniveauer+3; $j++) { $nyt[$i][$j] = 0; } } for ($i=1; $i<=$antal_kandidater; $i++) { $felt[$i][3+$niveau] = $kandidat[$i]{"modtagne_stemmer$niveau"}; if ($kandidat[$i]{'valgt'} >= $niveau) { $nyt[$i][3+$niveau] = 1; } if ($kandidat[$i]{'valgt'}>=$niveau) { $felt[$i][3] += $kandidat[$i]{"modtagne_stemmer$niveau"}; } } &ud_html($side++); for ($i=1; $i<=$antal_kandidater; $i++) { if ($kandidat[$i]{'valgt'} == $niveau) { $felt[$i][1] = $kandidat[$i]{'navn'}; if ($i<=$antal_pladser) { $felt[$i][2] = "Bestyrelsesmedlem"; } elsif ($i<=$antal_pladser+$antal_suppleanter) { $felt[$i][2] = "Suppleant"; } else { $felt[$i][2] = "Ikke valgt"; } $felt[$i][3] = "$niveau.$kandidat[$i]{'stemmer'}"; $nyt[$i][1] = 1; $nyt[$i][2] = 1; $nyt[$i][3] = 1; for ($j=$niveau+1; $j<=$prioritetsniveauer; $j++) { $felt[$i][$j+3] = $kandidat[$i]{"modtagne_stemmer$j"}; $nyt[$i][$j+3] = 1; } } } &ud_html($side++); } for ($i=1; $i<=$antal_kandidater; $i++) { for ($j=1; $j<=$prioritetsniveauer+2; $j++) { $nyt[$i][$j] = 0; } $felt[$i][1] = $kandidat[$i]{'navn'}; if ($felt[$i][2] eq " ") { $felt[$i][2] = "Ikke valgt"; } } &ud_html(0); # Få næstsidste side til at pege på det endelige resultat $side--; system("mv res-$side.html res-$side.html~"); system("sed -e \'s/^.*res-".($side+1).".*\$//\' < res-$side.html~ > res-$side.html"); system("rm res-$side.html~");