Fix duplicate use of VOTE_NO_VOTES.
[usenet/usevote.git] / UVmenu.pm
CommitLineData
ac7e2c54
TH
1# UVmenu: menu for interaction with the votetaker
2# Used by uvvote.pl, uvcfv.pl, uvcount.pl
3
4package UVmenu;
5
6use strict;
7use UVconfig;
8use UVmessage;
9use UVrules;
10use vars qw($VERSION);
11
12use Text::Wrap qw(wrap $columns);
13
14# Module version
15$VERSION = "0.4";
16
17##############################################################################
18# Menu for interaction with the votetaker #
19# Parameters: votes list and header (references to arrays) #
20# Body, Mailadress, Name, Ballot ID (references to strings) #
21# List of newly set fields (reference to array) #
22# List of errors to correct (Array-Ref) #
23# Return Values: 'w': proceed #
24# 'i': ignore (don't save vote) #
25##############################################################################
26
27sub menu {
28 my ($votes, $header, $body, $addr, $name, $ballot_id, $set, $errors) = @_;
29 my $input = "";
30 my $voter_addr = $$addr || '';
31 my $voter_name = $$name || '';
32 my @newvotes = @$votes;
33 my $mailonly = 0;
34 my %errors;
35 $$ballot_id ||= '';
36
37 foreach my $error (@$errors) {
38
39 # unrecognized vote: extract group number und display warning
40 if ($error =~ /^UnrecognizedVote #(\d+)#(.+)$/) {
41 $errors{UnrecognizedVote} ||= UVmessage::get("MENU_UNRECOGNIZEDVOTE");
42 $errors{UnrecognizedVote} .= "\n " . UVmessage::get("MENU_UNRECOGNIZED_LIST")
43 . " #$1: $2";
44
45 # violated rule: extract rule number and display warning
46 } elsif ($error =~ /^ViolatedRule #(\d+)$/) {
47 $errors{ViolatedRule} ||= UVmessage::get("MENU_VIOLATEDRULE", (RULE => "#$1"));
48
49 } else {
50 # special handling if called from uvballot.pl
51 $mailonly = 1 if ($error =~ s/Ballot$//);
52
53 # get error message for this error from messages.cfg
54 $errors{$error} = UVmessage::get("MENU_" . uc($error));
55 }
56 }
57
58 # This loop is only left by 'return'
59 while (1) {
60
61 system($config{clearcmd});
62 print UVmessage::get("MENU_PROBLEMS") . "\n";
63
64 foreach my $error (keys %errors) {
65 print "* $errors{$error}\n";
66 }
67
68 my $menucaption = UVmessage::get("MENU_CAPTION");
69 print "\n\n$menucaption\n";
70 print "=" x length($menucaption), "\n\n";
71 print "(1) ", UVmessage::get("MENU_SHOW_MAIL"), "\n\n",
72 UVmessage::get("MENU_CHANGE_PROPERTIES"), "\n",
73 "(2) ", UVmessage::get("MENU_ADDRESS"), " [$voter_addr]\n";
74
75 # don't print these options if called from uvcfv.pl
76 unless ($mailonly) {
77 print "(3) ", UVmessage::get("MENU_NAME"), " [$voter_name]\n";
78 print "(4) ", UVmessage::get("MENU_VOTES"), " [", @$votes, "]\n";
79 print "(5) ", UVmessage::get("MENU_BALLOT_ID"), " [$$ballot_id]\n"
80 if ($config{personal});
81 print "(6) ", UVmessage::get("MENU_BDSG"), "\n" if ($config{bdsg});
82 }
83
84 print "\n",
85 "(i) ", UVmessage::get("MENU_IGNORE"), "\n",
86 "(w) ", UVmessage::get("MENU_PROCEED"), "\n\n",
87 UVmessage::get("MENU_PROMPT");
88
89 do { $input = <STDIN>; } until ($input);
90 chomp $input;
91 print "\n";
92
93 # only accept 1, 2, i and w if called from uvcfv.pl
94 next if ($mailonly && $input !~ /^[12iw]$/i);
95
96 if ($input eq '1') {
97 system($config{clearcmd});
98 # ignore SIGPIPE (Bug in more and less)
99 $SIG{PIPE} = 'IGNORE';
100 open (MORE, "|$config{pager}");
101 print MORE join("\n", @$header), "\n\n", $$body, "\n";
102 close (MORE);
103
104 print "\n", UVmessage::get("MENU_GETKEY");
105 $input = <STDIN>;
106
107 } elsif ($input eq '2') {
108 my $sel;
109 do {
110 print "[a] ", UVmessage::get("MENU_ADDRESS_OK"), "\n",
111 "[b] ", UVmessage::get("MENU_ADDRESS_CHANGE"), "\n",
112 "[c] ", UVmessage::get("MENU_ADDRESS_INVALID"), "\n\n",
113 UVmessage::get("MENU_PROMPT");
114 $sel = <STDIN>;
115 } until ($sel =~ /^[abc]$/i);
116 if ($sel =~ /^a$/i) {
117 delete $errors{SuspiciousAccount};
118 delete $errors{InvalidAddress};
119 next;
120 } elsif ($sel =~ /^c$/i) {
121 delete $errors{SuspiciousAccount};
122 $errors{InvalidAddress} = UVmessage::get("MENU_INVALIDADDRESS") . " " .
123 UVmessage::get("MENU_INVALIDADDRESS2");
124 next;
125 }
126
127 do {
128 print "\n", UVmessage::get("MENU_ADDRESS_PROMPT"), " ";
129 $voter_addr = <STDIN>;
130 chomp ($voter_addr);
131 } until ($voter_addr);
132 $$addr = $voter_addr;
133 push (@$set, 'Adresse');
134 delete $errors{SuspiciousAccount};
135 delete $errors{InvalidAddress};
136 check_ballotid(\%errors, \$voter_addr, $ballot_id, \%ids);
137
138 } elsif ($input eq '3') {
139 my $sel;
140 do {
141 print "[a] ", UVmessage::get("MENU_NAME_OK"), "\n",
142 "[b] ", UVmessage::get("MENU_NAME_CHANGE"), "\n",
143 "[c] ", UVmessage::get("MENU_NAME_INVALID"), "\n\n",
144 UVmessage::get("MENU_PROMPT");
145 $sel = <STDIN>;
146 } until ($sel =~ /^[abc]$/i);
147 if ($sel =~ /^a$/i) {
148 delete $errors{InvalidName};
149 next;
150 } elsif ($sel =~ /^c$/i) {
151 $errors{InvalidName} = UVmessage::get("MENU_INVALIDNAME");
152 next;
153 }
154 print UVmessage::get("MENU_NAME"), ": ";
155 $voter_name = <STDIN>;
156 chomp ($voter_name);
157 $$name = $voter_name;
158 push (@$set, 'Name');
159 delete $errors{NoName};
160 delete $errors{InvalidName};
161
162 $errors{InvalidName} = UVmessage::get("MENU_INVALIDNAME")
163 unless ($voter_name =~ /$config{name_re}/);
164
165 } elsif ($input eq '4') {
166 # set votes
167
168 my $sel;
169 do {
170 print "[a] ", UVmessage::get("MENU_VOTES_OK"), "\n",
171 "[b] ", UVmessage::get("MENU_VOTES_RESET"), "\n",
172 "[c] ", UVmessage::get("MENU_VOTES_INVALID"), "\n",
173 "[d] ", UVmessage::get("MENU_VOTES_CANCELLED"), "\n\n",
174 UVmessage::get("MENU_PROMPT");
175 $sel = <STDIN>;
176 } until ($sel =~ /^[abcd]$/i);
177 if ($sel =~ /^[ad]$/i) {
178 delete $errors{NoVote};
179 delete $errors{UnrecognizedVote};
180 delete $errors{ViolatedRule};
181 delete $errors{DuplicateVote};
182 if ($sel =~ /^d$/i) {
183 # cancelled vote: replace all votes with an A
184 @$votes = split(//, 'A' x scalar @groups);
185 push @$set, 'Stimmen';
186 # some errors are irrelevant when cancelling a vote:
187 delete $errors{InvalidName};
188 delete $errors{NoName};
189 delete $errors{InvalidBDSG};
190 delete $errors{InvalidAddress};
191 delete $errors{SuspiciousAccount};
192 }
193 next;
194 } elsif ($sel =~ /^c$/i) {
195 $errors{NoVote} = UVmessage::get("MENU_INVALIDVOTE");
196 next;
197 }
198
199 # Set columns for Text::Wrap
200 $columns = $config{rightmargin};
201 print "\n", wrap('', '', UVmessage::get("MENU_VOTES_REENTER_ASK")), "\n\n";
202 print UVmessage::get("MENU_VOTES_REENTER_LEGEND"), "\n";
203
204 for (my $n=0; $n<@groups; $n++) {
205 my $voteinput = "";
206 $votes->[$n] ||= 'E';
207
208 # repeat while invalid character entered
209 while (!($voteinput =~ /^[JNE]$/)) {
210 my $invalid = $#groups ? 0 : 1;
211 print UVmessage::get("MENU_VOTES_REENTER", (GROUP => $groups[$n]));
212 $voteinput = <STDIN>;
213 chomp $voteinput;
214 $voteinput ||= $votes->[$n];
215 $voteinput =~ tr/jne/JNE/;
216 }
217
218 # valid input, save new votes
219 $newvotes[$n] = $voteinput;
220 }
221
222 print "\n\n";
223 my $oldvotes = UVmessage::get("MENU_VOTES_REENTER_OLD");
224 my $newvotes = UVmessage::get("MENU_VOTES_REENTER_NEW");
225 my $oldlen = length($oldvotes);
226 my $newlen = length($newvotes);
227 my $maxlen = 1 + (($newlen>$oldlen) ? $newlen : $oldlen);
228 print $oldvotes, ' ' x ($maxlen - length($oldvotes)), @$votes, "\n",
229 $newvotes, ' ' x ($maxlen - length($newvotes)), @newvotes, "\n\n";
230
231 do {
232 print "[a] ", UVmessage::get("MENU_VOTES_REENTER_ACK"), " ",
233 "[b] ", UVmessage::get("MENU_VOTES_REENTER_NACK"), "\n\n",
234 UVmessage::get("MENU_PROMPT");
235 $sel = <STDIN>;
236 } until ($sel =~ /^[ab]$/i);
237
238 next if ($sel =~ /^b$/i);
239 @$votes = @newvotes;
240 push @$set, 'Stimmen';
241 delete $errors{UnrecognizedVote};
242 delete $errors{DuplicateVote};
243 delete $errors{NoVote};
244 delete $errors{ViolatedRule};
245
246 if (my $rule = UVrules::rule_check($votes)) {
247 $errors{ViolatedRule} = UVmessage::get("MENU_VIOLATEDRULE", (RULE => "#$rule"));
248 }
249
250 } elsif ($input eq '5' && $config{personal}) {
251 print "\n", UVmessage::get("MENU_BALLOT_ID"), ": ";
252 $$ballot_id = <STDIN>;
253 chomp ($$ballot_id);
254 push (@$set, 'Kennung');
255 check_ballotid(\%errors, \$voter_addr, $ballot_id, \%ids);
256
257 } elsif ($input eq '6' && $config{bdsg}) {
258 my $sel;
259 do {
260 print "[a] ", UVmessage::get("MENU_BDSG_ACCEPTED"), "\n",
261 "[b] ", UVmessage::get("MENU_BDSG_DECLINED"), "\n\n",
262 UVmessage::get("MENU_PROMPT");
263 $sel = <STDIN>;
264 } until ($sel =~ /^[ab]$/i);
265
266 if ($sel =~ /^a$/i) {
267 delete $errors{InvalidBDSG};
268 } else {
269 $errors{InvalidBDSG} = UVmessage::get("MENU_INVALIDBDSG");
270 }
271
272 } elsif ($input =~ /^i$/i) {
273 my $ignore = UVmessage::get("MENU_IGNORE_STRING");
274 # Set columns for Text::Wrap
275 $columns = $config{rightmargin};
276 print wrap('', '', UVmessage::get("MENU_IGNORE_WARNING",
277 (MENU_IGNORE_STRING => $ignore)
278 ));
279 if (<STDIN> eq "$ignore\n") {
280 print "\n";
281 return "i";
282 }
283
284 } elsif ($input =~ /^w$/i) {
285
286 if (keys %errors) {
287 if ((keys %errors)==1 && $errors{UnrecognizedVote}) {
288 # unrecognized vote lines aren't errors if votetaker
289 # did not change them
290 @$errors = ();
291 } else {
292 # Set columns for Text::Wrap
293 $columns = $config{rightmargin};
294 @$errors = keys %errors;
295 my $warning = ' ' . UVmessage::get("MENU_ERROR_WARNING") . ' ';
296 my $length = length($warning);
297 print "\n", '*' x (($config{rightmargin}-$length)/2), $warning,
298 '*' x (($config{rightmargin}-$length)/2), "\n\n",
299 wrap('', '', UVmessage::get("MENU_ERROR_TEXT")), "\n\n",
300 '*' x $config{rightmargin}, "\n\n",
301 UVmessage::get("MENU_ERROR_GETKEY");
302 my $input = <STDIN>;
303 next if ($input !~ /^y$/i);
304 print "\n";
305 }
306 } else {
307 @$errors = ();
308 }
309
310 system($config{clearcmd});
311 print "\n", UVmessage::get("MENU_PROCESSING"), "\n";
312 return "w";
313 }
314 }
315
316 sub check_ballotid {
317 my ($errors, $voter_addr, $ballot_id, $ids) = @_;
318
319 return 0 unless ($config{personal});
320
321 delete $errors->{NoBallotID};
322 delete $errors->{WrongBallotID};
323 delete $errors->{AddressNotRegistered};
324
325 if ($$ballot_id) {
326 if ($ids->{$$voter_addr}) {
327 if ($ids->{$$voter_addr} ne $$ballot_id) {
328 # ballot id incorrect
329 $errors->{WrongBallotID} = UVmessage::get("MENU_WRONGBALLOTID");
330 }
331 } else {
332 $errors->{AddressNotRegistered} = UVmessage::get("MENU_ADDRESSNOTREGISTERED");
333 }
334 } else {
335 $errors->{NoBallotID} = UVmessage::get("MENU_NOBALLOTID");
336 }
337 }
338
339}
340
341
342##############################################################################
343# Menu for sorting out duplicate votings manually #
344# Parameters: References to hashes with the paragraphs from the result file #
345# and the default value #
346# Return value: selected menu item (1, 2 or 0) #
347##############################################################################
348
349sub dup_choice {
350 my ($vote1, $vote2, $default) = @_;
351
352 print STDERR "\n", UVmessage::get("MENU_DUP_VOTE"), "\n\n";
353 print STDERR UVmessage::get("MENU_DUP_FIRST"), "\n";
354 print STDERR "A: $vote1->{A}\n";
355 print STDERR "N: $vote1->{N}\n";
356 print STDERR "D: $vote1->{D}\n";
357 print STDERR "K: $vote1->{K}\n";
358 print STDERR "S: $vote1->{S}\n\n";
359 print STDERR UVmessage::get("MENU_DUP_SECOND"), "\n";
360 print STDERR "A: $vote2->{A}\n";
361 print STDERR "N: $vote2->{N}\n";
362 print STDERR "D: $vote2->{D}\n";
363 print STDERR "K: $vote2->{K}\n";
364 print STDERR "S: $vote2->{S}\n\n";
365 print STDERR "1: ", UVmessage::get("MENU_DUP_DELFIRST"), "\n",
366 "2: ", UVmessage::get("MENU_DUP_DELSECOND"), "\n",
367 "0: ", UVmessage::get("MENU_DUP_DELNONE"), "\n\n";
368
369 my $input;
370
371 do {
372 print STDERR UVmessage::get("MENU_PROMPT"), "[$default] ";
373 $input = <STDIN>;
374 chomp $input;
375 } until ($input eq '' || ($input >= 0 && $input<3));
376
377 return $input || $default;
378}
379
3801;
This page took 0.026683 seconds and 4 git commands to generate.