-
Notifications
You must be signed in to change notification settings - Fork 28
/
convert-rankings.pl
executable file
·133 lines (114 loc) · 2.88 KB
/
convert-rankings.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/usr/bin/env perl
use strict 'refs';
use warnings;
use Text::CSV;
use Text::CSV::Encoded;
use File::Basename;
use Scalar::Util qw(looks_like_number);
sub usage {
my $base = &basename($0);
print STDERR "Usage: $base <ranking.csv>\n\n";
print STDERR " Converts ballots in ordering format into CIVS format.\n";
print STDERR " For example, a file containing:\n\n";
print STDERR "a,b,c,d\n";
print STDERR "c,a,b,e\n";
print STDERR "a,c,b,d\n";
print STDERR "\n produces output as follows:\n";
print STDERR '
### list of choices ###
a
b
c
d
e
### ballots ###
1,2,3,4,-
2,3,1,-,4
1,3,2,4,-', "\n";
exit 1;
}
my $nl = "\r\n";
my $csv = Text::CSV::Encoded->new({ encoding_in => "UTF-8",
encoding_out => "UTF-8" });
# The sources that must be present in each output row
my %req_sources;
# merge rows with duplicate keys in the same file?
my $merge_dups = 0;
# report source files?
my $report_sources = 0;
sub TrimSuffix {
my $result = $_[0];
$result =~ s/\.csv$//;
return $result;
}
while ($#ARGV >= 0 && $ARGV[0] =~ /^-/) {
my $opt = shift @ARGV;
print STDERR "Unknown option $opt.\n";
usage()
}
my @req_sources = keys %req_sources;
# print STDERR "Requiring keys to be in these files: ", (join ', ', @req_sources), "\n";
my $nreq_sources = 1 + $#req_sources;
# remove leading and trailing whitespace and commas and
# collapse multiple whitespace into one.
sub clean {
my $x = $_[0];
chomp $x;
$x =~ s/\s*$//g;
$x =~ s/\s\s+$/ /g;
$x =~ s/^\s*//g;
$x =~ s/,*$//g;
$x =~ s/^,*//g;
return $x;
}
if ($#ARGV < 0) {
usage();
exit(1);
}
my $file = $ARGV[0];
open my $fileh, '<', $file;
my %names;
my @orderings = ();
my $num_rows = 0;
while (1) {
my $row = $csv->getline($fileh);
if (!defined($row)) { last; }
my @ordering = @{$row};
# printf "%s\n", join ",", @{$row};
foreach my $name (@ordering) {
$name = &clean($name);
$names{$name} = 1;
}
$orderings[$num_rows++] = $row;
}
# print "number of rows: $num_rows\n";
my @name_list = sort {
if (looks_like_number($a) && looks_like_number($b)) { return $a <=> $b }
if (looks_like_number($a)) { return -1 }
if (looks_like_number($b)) { return 1 }
return $a cmp $b
} (keys %names);
my $num_names = $#name_list + 1;
# print "number of names: $num_names\n";
print "### list of choices ###\n";
foreach my $name (@name_list) {
print "$name\n";
}
print "### ballots ###\n";
for (my $i = 0; $i < $num_rows; $i++) {
my @ordering = @{$orderings[$i]};
my $first = 1;
foreach my $name (@name_list) {
my $rank = "-";
print "," unless $first;
$first = 0;
for ($j = 0; $j <= $#ordering; $j++) {
if ($ordering[$j] eq $name) {
$rank = $j + 1;
last;
}
}
print $rank;
}
print "\n";
}