4 # normalise [NORM-OPTIONS...] [--] INPUT-FILES...
7 # +OPTNAME[=OPTVAL] Election option
9 # +CAND+OPTNAME[=OPTVAL] Candidate option
10 # -- End of options to normalise
11 # -... Reserved for future options to normalise
16 our %candidates; # $candidates{CAND}{Desc}, {Opts}[]
19 my $candvoter_re = '\w+';
20 my $opt_re = '\w+(?:=\S*)?';
23 die "bad input: $_[0]";
26 sub normalise_opts_list ($$) {
27 # $ctx is one of Election Candidate Ballot
31 foreach my $o (split /\s+/, $os) {
34 } elsif ($o =~ m/^\w+\=\S+$/) {
36 } elsif ($o !~ m/\S/) {
38 badinput "bad option \`$o'";
44 sub normalise_opts ($$) {
46 my @o = normalise_opts_list $os, $ctx;
50 sub setcanddesc ($$) {
51 my ($cand,$desc) = @_;
54 badinput "multiple descriptions for $cand" if
55 defined $candidates{$cand}{Desc};
56 $candidates{$cand}{Desc} = $desc;
64 } elsif (m/^(\w+)=([^|]+)$/) {
66 } elsif (m/^\+($opt_re)$/) {
68 } elsif (m/^\+(\w+)\+($opt_re)$/) {
69 push @{ $candidates{$1}{Opts} }, $2;
71 die "unknown normalise option \`$_'\n";
85 push @options, normalise_opts_list $', 'Election';
86 } elsif (m/^($candvoter_re?)\s*=\s*([^|]+?)\s*\|(.*)?$/o) {
88 print STDERR Dumper($1,$2,$3);
89 my ($cand,$desc,$opts) = ($1,$2,$3);
90 push @{ $candidates{$cand}{Opts} }, normalise_opts $opts, 'Candidate';
91 setcanddesc $cand, $desc;
92 } elsif (m/^($candvoter_re?)?\s*\:([^|]*)(?:\|(.*))?$/) {
93 my ($voter,$opts) = ($1,$3);
95 foreach my $p (split /\s+/, $2) {
96 if ($p =~ m/^\w+(?:\=\w+)*$/) {
98 $candidates{$_} //= { } foreach $p =~ m/\w+/g;
100 # empty entry can only happen if voter casts no prefs at all
102 badinput "bad vote preference \`$p'";
105 push @ballots, "$voter : @p".normalise_opts $opts, 'Ballot';
108 badinput "unknown line format \`$_'";
112 print "| @options\n" or die $!;
114 foreach my $cand (sort keys %candidates) {
115 my $c = $candidates{$cand};
116 $c->{Desc} //= $cand;
118 my $opts = $c->{Opts};
119 print "$cand = $c->{Desc} | @$opts\n" or die $!;
122 sub vsortkey { $_[0] =~ m/:/; return "$' : $`"; }
124 print $_,"\n" or die $! foreach
125 sort { vsortkey($a) cmp vsortkey($b) } @ballots;
127 print ".\n" or die $!;