File Coverage

blib/lib/Voting/VoteFairRanking.pm
Criterion Covered Total %
statement 2524 3377 74.7
branch 841 1598 52.6
condition 103 162 63.5
subroutine 28 32 87.5
pod 29 29 100.0
total 3525 5198 67.8


line stmt bran cond sub pod time code
1             package Voting::VoteFairRanking;
2              
3 2     2   53949 use strict;
  2         6  
  2         99  
4 2     2   12 use warnings;
  2         4  
  2         2674  
5             require Exporter;
6              
7             =head1 NAME
8              
9             Voting::VoteFairRanking - Calculates VoteFair Ranking results
10              
11             =cut
12              
13              
14             =head1 VERSION
15              
16             Version 5.01
17              
18             =cut
19              
20             our $VERSION = '5.01' ;
21              
22              
23             =head1 SYNOPSIS
24              
25             VoteFair Ranking is described at www.VoteFair.org and in the book "Ending The Hidden Unfairness In U.S. Elections" by Richard Fobes. The components of VoteFair Ranking that are implemented here are briefly described below in the ABOUT section.
26              
27             The following sample code executes this module.
28              
29             use Voting::VoteFairRanking;
30             &Voting::VoteFairRanking::votefair_read_calculate_write( );
31              
32             This usage assumes that you supply via STDIN (standard input) a file that contains the appropriately formatted election/survey/poll data, and that you direct the output via STDOUT (standard output) to a file. These input and output files can be handled most easily by using Vote-Info-Split-Join (VISJ) files, which are available on GitHub in the CPSolver account. The VISJ framework uses the Language::Dashrep module.
33              
34             Alternatively, this module can be accessed from any Perl software by directly using these subroutines:
35              
36             =over
37              
38             =item * votefair_put_next_vote_info_number
39              
40             =item * votefair_do_calculations_all_questions
41              
42             =item * votefair_get_next_result_info_number
43              
44             =back
45              
46             (c) Copyright 1991 through 2011 Richard Fobes at www.VoteFair.org. You can redistribute and/or modify this VoteFairRanking library module under the Perl Artistic license version 2.0 (a copy of which is included in the LICENSE file). As required by the license this full copyright notice must be included in all copies of this software.
47              
48             Conversion of this code into another programming language is also covered by the above license terms.
49              
50             The mathematical algorithms of VoteFair Ranking are in the public domain.
51              
52             =cut
53              
54              
55             =head1 ABOUT
56              
57             This module calculates VoteFair Ranking results. The portions of VoteFair Ranking implemented here are:
58              
59             =over
60              
61             =item * VoteFair popularity ranking. This voting method calculates the full popularity ranking of all candidates (or choices in the case of a survey) from most popular and second-most popular down to least popular. It uses the preference information collected on 1-2-3 ballots (or any equivalent way of expressing "ranked" preferences). When a single position is being filled, the most popular candidate is declared the winner. This calculation method is mathematically equivalent to the Condorcet-Kemeny election method.
62              
63             =item * VoteFair representation ranking. This voting method is used to elect a second candidate who represents the voters who are not well-represented by the most-popular candidate, or to fill multiple board-of-director positions, or to choose a second simultaneous activity in addition to the most popular activity. This method reduces the influence of the voters who are already well-represented by the most popular candidate (or choice), and it does so in a way that protects against strategic voting. If instead the second-most popular candidate as identified by VoteFair popularity ranking were chosen, the same voters who prefer the first winner also can determine the second winner, and this can leave large numbers of other voters unrepresented. Additional levels of representation ranking can be used to fill additional seats, although VoteFair partial-proportional ranking should be used instead if "proportional representation" of political parties is needed, especially for the purpose of defeating attempts to gerrymander district boundaries.
64              
65             =item * VoteFair party ranking. This voting method ranks political parties according to a different kind of "popularity". The results can be used in high-stakes elections to limit the number of candidates allowed by each party. In such cases the two or three political parties that are ranked highest can be limited to offering just two candidates from each party, and lower-ranked parties can be allowed to offer one candidate each, and any additional parties can be prohibited from offering any candidate (because those parties are too unpopular and too unrepresentative). Such limits have not been needed in the past because the fear of vote splitting has limited each political party to offering just one candidate in each contest.
66              
67             =back
68              
69             For detailed descriptions of VoteFair Ranking, see www.VoteFair.org or the book "Ending The Hidden Unfairness In U.S. Elections" by Richard Fobes.
70              
71             In addition to being useful for elections, VoteFair Ranking also is useful for calculating results for surveys and polls, ranking the popularity of songs and movies, and much more.
72              
73             In mathematical terms, VoteFair Ranking is useful for doing "combinatorial optimization" and may be useful for solving the "linear ordering problem". See Wikipedia for details about these terms.
74              
75             =cut
76              
77              
78             =head1 EXPORT
79              
80             The following subroutines are exported:
81              
82             =over
83              
84             =item * votefair_read_calculate_write
85              
86             =item * votefair_put_next_vote_info_number
87              
88             =item * votefair_do_calculations_all_questions
89              
90             =item * votefair_get_next_result_info_number
91              
92             =item * votefair_put_input_string
93              
94             =item * votefair_get_output_string
95              
96             =item * votefair_always_do_rep_and_party_ranking
97              
98             =item * votefair_start_new_cases
99              
100             =back
101              
102             =cut
103              
104              
105             our @ISA = qw(Exporter);
106             our @EXPORT = qw(
107             votefair_read_calculate_write
108             votefair_put_next_vote_info_number
109             votefair_do_calculations_all_questions
110             votefair_get_next_result_info_number
111             votefair_put_input_string
112             votefair_get_output_string
113             votefair_always_do_rep_and_party_ranking
114             votefair_start_new_cases
115             );
116              
117              
118             #-------------------------------------------
119             #
120             # IMPORTANT NOTE TO CODERS!
121             #
122             # This Perl code is intentionally written
123             # in a subset of Perl that is close to
124             # what can be written in the C language.
125             # (Every line that contains a quotation
126             # mark must not be necessary for correct
127             # calculations, and such lines should
128             # only involve unchanging text that is
129             # only used for diagnostic or
130             # identification purposes.)
131             # This approach allows this code to be
132             # easily ported to the C language, which
133             # is directly recognized by C++, C#, and
134             # Objective-C compilers, as well as the
135             # widely ported "gcc" compiler.
136             # The goal is to eventually create a
137             # C version that runs very fast on most
138             # operating systems (and most
139             # environments).
140             #
141             # If you offer improvements to this code,
142             # please follow this convention so that
143             # the code continues to be easily
144             # convertible into the C language.
145             #-------------------------------------------
146              
147              
148             #-----------------------------------------------
149             #
150             # Explanation about VISJ
151             #
152             # Vote-Info-Split-Join (VISJ) is a software
153             # framework that handles all text-related
154             # information extracted from an EML or XML
155             # or JSON data file. This allows the VoteFair
156             # Ranking software to just handle numbers
157             # (and a few error messages and optional
158             # debugging information). The VISJ software
159             # is open-source software that is available
160             # on GitHub in the CPSolver account.
161              
162              
163             #-----------------------------------------------
164             #-----------------------------------------------
165             #
166             # History
167             #
168             # Version 1.0 -- In 1991 (approximately) Richard
169             # Fobes wrote the subroutine (now named
170             # calc_all_sequence_scores) that calculates
171             # VoteFair popularity ranking results.
172             #
173             # Version 2.0 -- In 1997 (approximately) Richard
174             # Fobes created the web-page-server (CGI)
175             # software that calculates VoteFair Ranking
176             # results at VoteFair.org. It uses a modified
177             # version of the calc_all_sequence_scores
178             # subroutine, and added subroutines including
179             # the get_numbers_based_on_one_ballot and
180             # add_preferences_to_tally_table and related
181             # subroutines.
182             #
183             # Version 3.0 -- In 2005 Richard Fobes wrote
184             # the subroutine that calculates VoteFair
185             # representation ranking results, which is now
186             # named the calc_votefair_representation_rank
187             # subroutine.
188             #
189             # Version 4.0 -- In 2011 Richard Fobes wrote
190             # the calc_votefair_party_rank subroutine that
191             # calculates VoteFair party ranking results,
192             # and wrote the remainder of this module to
193             # use the VISJ framework.
194             #
195             # Version 4.9 -- In 2011 this module was added
196             # to Perl's CPAN archives.
197             #
198             # Version 5.0 -- In 2011 (December) the
199             # calc_votefair_choice_specific_pairwise_score_popularity_rank
200             # and
201             # calc_votefair_insertion_sort_popularity_rank
202             # subroutines were added. These subroutines,
203             # when used together, calculate VoteFair
204             # popularity ranking results fast -- in
205             # "polynomial time". These two subroutines
206             # were developed during the year 2011, as
207             # improvements over the also-fast calculation
208             # subroutine used at VoteFair.org since about
209             # the year 2000.
210              
211              
212             #-----------------------------------------------
213             #-----------------------------------------------
214             # Declare package variables.
215              
216             my $global_true ;
217             my $global_false ;
218              
219             # Input and output codes that identify
220             # the meaning of the next number in the (coded) list.
221              
222             my $global_voteinfo_code_for_start_of_all_cases ;
223             my $global_voteinfo_code_for_end_of_all_cases ;
224             my $global_voteinfo_code_for_case_number ;
225             my $global_voteinfo_code_for_question_number ;
226             my $global_voteinfo_code_for_number_of_choices ;
227             my $global_voteinfo_code_for_start_of_all_vote_info ;
228             my $global_voteinfo_code_for_end_of_all_vote_info ;
229             my $global_voteinfo_code_for_start_of_ballot ;
230             my $global_voteinfo_code_for_end_of_ballot ;
231             my $global_voteinfo_code_for_ballot_count ;
232             my $global_voteinfo_code_for_choice ;
233             my $global_voteinfo_code_for_tie ;
234             my $global_voteinfo_code_for_special_request ;
235             my $global_voteinfo_code_for_start_of_votefair_popularity_ranking_results ;
236             my $global_voteinfo_code_for_end_of_votefair_popularity_ranking_results ;
237             my $global_voteinfo_code_for_start_of_votefair_representation_ranking_results ;
238             my $global_voteinfo_code_for_end_of_votefair_representation_ranking_results ;
239             my $global_voteinfo_code_for_start_of_votefair_party_ranking_results ;
240             my $global_voteinfo_code_for_end_of_votefair_party_ranking_results ;
241             my $global_voteinfo_code_for_early_end_of_ranking ;
242             my $global_voteinfo_code_for_next_ranking_level ;
243             my $global_voteinfo_code_for_start_of_tally_table_results ;
244             my $global_voteinfo_code_for_end_of_tally_table_results ;
245             my $global_voteinfo_code_for_first_choice ;
246             my $global_voteinfo_code_for_second_choice ;
247             my $global_voteinfo_code_for_tally_first_over_second ;
248             my $global_voteinfo_code_for_tally_second_over_first ;
249             my $global_voteinfo_code_for_start_of_plurality_results ;
250             my $global_voteinfo_code_for_end_of_plurality_results ;
251             my $global_voteinfo_code_for_plurality_count ;
252             my $global_voteinfo_code_for_skip_case ;
253             my $global_voteinfo_code_for_skip_question ;
254             my $global_voteinfo_code_for_request_only_plurality_results ;
255             my $global_voteinfo_code_for_request_pairwise_counts ;
256             my $global_voteinfo_code_for_request_no_pairwise_counts ;
257             my $global_voteinfo_code_for_request_votefair_representation_rank ;
258             my $global_voteinfo_code_for_request_no_votefair_representation_rank ;
259             my $global_voteinfo_code_for_request_votefair_party_rank ;
260             my $global_voteinfo_code_for_request_no_votefair_party_rank ;
261             my $global_voteinfo_code_for_start_of_votefair_popularity_ranking_sequence_results ;
262             my $global_voteinfo_code_for_end_of_votefair_popularity_ranking_sequence_results ;
263             my $global_voteinfo_code_for_start_of_votefair_popularity_ranking_levels_results ;
264             my $global_voteinfo_code_for_end_of_votefair_popularity_ranking_levels_results ;
265             my $global_voteinfo_code_for_start_of_votefair_representation_ranking_sequence_results ;
266             my $global_voteinfo_code_for_end_of_votefair_representation_ranking_sequence_results ;
267             my $global_voteinfo_code_for_start_of_votefair_representation_ranking_levels_results ;
268             my $global_voteinfo_code_for_end_of_votefair_representation_ranking_levels_results ;
269             my $global_voteinfo_code_for_start_of_votefair_party_ranking_sequence_results ;
270             my $global_voteinfo_code_for_end_of_votefair_party_ranking_sequence_results ;
271             my $global_voteinfo_code_for_start_of_votefair_party_ranking_levels_results ;
272             my $global_voteinfo_code_for_end_of_votefair_party_ranking_levels_results ;
273              
274             # Input codes that keep track of special calculation
275             # requests.
276              
277             my $global_voteinfo_code_for_true_or_false_request_only_plurality_results ;
278             my $global_voteinfo_code_for_true_or_false_request_votefair_representation_rank ;
279             my $global_voteinfo_code_for_true_or_false_request_votefair_party_rank ;
280              
281             # Lists related to input.
282              
283             my @global_vote_info_list ;
284              
285             # Lists related to output.
286              
287             my @global_output_results ;
288             my @global_string_for_negative_of_code ;
289              
290             # Lists related to results.
291              
292             my @global_plurality_count_for_actual_choice ;
293             my @global_popularity_ranking_for_actual_choice ;
294             my @global_full_popularity_ranking_for_actual_choice ;
295             my @global_representation_ranking_for_actual_choice ;
296             my @global_full_representation_ranking_for_actual_choice ;
297             my @global_party_ranking_for_actual_choice ;
298              
299             # Input/output-related pointers and variables.
300              
301             my $global_supplied_vote_info_text ;
302             my $global_input_pointer_start_next_case ;
303             my $global_pointer_to_current_ballot ;
304             my $global_length_of_vote_info_list ;
305             my $global_max_array_length ;
306             my $global_pointer_to_output_results ;
307             my $global_length_of_result_info_list ;
308             my $global_combined_case_number_and_question_number ;
309             my $global_combined_case_number_and_question_number_and_choice_number ;
310              
311             # Flags indicating which results are to be calculated, and
312             # what other choices to make.
313              
314             my $global_true_or_false_request_votefair_popularity_rank ;
315             my $global_true_or_false_request_only_plurality_results ;
316             my $global_true_or_false_always_request_only_plurality_results ;
317             my $global_true_or_false_request_no_pairwise_counts ;
318             my $global_true_or_false_always_request_no_pairwise_counts ;
319             my $global_true_or_false_request_votefair_representation_rank ;
320             my $global_true_or_false_always_request_votefair_representation_rank ;
321             my $global_true_or_false_request_votefair_party_rank ;
322             my $global_true_or_false_always_request_votefair_party_rank ;
323             my $global_true_or_false_request_dashrep_phrases_in_output ;
324              
325             # Miscellaneous variables.
326              
327             my $global_begin_module_actions_done ;
328             my $global_intitialization_done ;
329             my $global_case_number ;
330             my $global_previous_case_number ;
331             my $global_maximum_case_number ;
332             my $global_question_number ;
333             my $global_maximum_question_number ;
334             my $global_ballot_info_repeat_count ;
335             my $global_current_total_vote_count ;
336             my $global_ballot_influence_amount ;
337             my $global_choice_number ;
338             my $global_adjusted_choice_number ;
339             my $global_adjusted_choice_count ;
340             my $global_full_choice_count ;
341             my $global_maximum_choice_number ;
342             my $global_pair_counter_maximum ;
343             my $global_true_or_false_tally_table_created ;
344             my $global_question_count ;
345             my $global_choice_count_at_top_popularity_ranking_level ;
346             my $global_choice_count_at_full_top_popularity_ranking_level ;
347             my $global_choice_count_at_full_second_representation_level ;
348             my $global_limit_on_popularity_rank_levels ;
349             my $global_check_all_scores_choice_limit ;
350             my $global_representation_levels_requested ;
351             my $global_limit_on_representation_rank_levels ;
352             my $global_number_of_questions_in_current_case ;
353             my $global_output_warning_message ;
354             my $global_case_specific_warning_begin ;
355             my $global_question_specific_warning_begin ;
356             my $global_pairwise_matrix_text ;
357             my $global_first_most_popular_actual_choice ;
358             my $global_second_most_representative_actual_choice ;
359             my $global_maximum_twice_highest_possible_score ;
360             my $global_log_filename ;
361             my $global_error_message_filename ;
362             my $global_possible_error_message ;
363             my $global_output_warning_messages_case_or_question_specific ;
364             my $global_actual_choice_at_top_of_full_popularity_ranking ;
365             my $global_actual_choice_at_second_representation_ranking ;
366             my $global_ranking_type_being_calculated ;
367             my $global_warning_end ;
368             my $global_count_of_popularity_rankings ;
369             my $global_logging_info ;
370             my $global_voteinfo_code_for_total_ballot_count ;
371             my $global_actual_choice_at_top_popularity_ranking_level ;
372             my $global_default_representation_levels_requested ;
373             my $global_true_or_false_always_request_dashrep_phrases_in_output ;
374             my $global_code_associations_filename ;
375             my $global_voteinfo_code_for_preference_level ;
376             my $global_voteinfo_code_for_ranking_level ;
377              
378             # Lists for internal use.
379              
380             my @global_question_count_for_case ;
381             my @global_true_or_false_ignore_case ;
382             my @global_choice_count_for_case_and_question ;
383             my @global_adjusted_choice_for_actual_choice ;
384             my @global_actual_choice_for_adjusted_choice ;
385             my @global_adjusted_first_choice_number_in_pair ;
386             my @global_adjusted_second_choice_number_in_pair ;
387             my @global_using_choice ;
388             my @global_tally_first_over_second_in_pair ;
389             my @global_tally_second_over_first_in_pair ;
390             my @global_tally_first_equal_second_in_pair ;
391             my @global_ballot_preference_for_choice ;
392             my @global_adjusted_ranking_for_adjusted_choice_bottom_up_version ;
393             my @global_adjusted_ranking_for_adjusted_choice_top_down_version ;
394             my @global_pair_counter_offset_for_first_adjusted_choice ;
395             my @global_log_info_choice_at_position ;
396             my @global_rank_to_normalize_for_adjusted_choice ;
397              
398             my %global_code_number_for_letters ;
399              
400             my $global_scale_for_logged_pairwise_counts ;
401             my $global_comparison_count ;
402             my $global_sequence_score ;
403             my $global_not_same_count ;
404             my $global_sequence_score_using_choice_score_method ;
405             my $global_sequence_score_using_insertion_sort_method ;
406             my $global_sequence_score_using_all_scores_method ;
407             my $global_top_choice_according_to_choice_specific_scores ;
408              
409             my @global_choice_score_popularity_rank_for_actual_choice ;
410             my @global_insertion_sort_popularity_rank_for_actual_choice ;
411              
412              
413             #-----------------------------------------------
414             #-----------------------------------------------
415             # Indicate whether the first actions of this
416             # module have been done.
417              
418             BEGIN {
419              
420 2     2   6 $global_true = 1 ;
421 2         8 $global_false = 0 ;
422 2         12 $global_begin_module_actions_done = $global_false ;
423 2         4 $global_intitialization_done = $global_false ;
424 2         88538 $global_logging_info = $global_false ;
425              
426             }
427              
428              
429             #-----------------------------------------------
430             #-----------------------------------------------
431              
432             =head1 FUNCTIONS
433              
434             =cut
435              
436             #-----------------------------------------------
437             #-----------------------------------------------
438              
439              
440              
441              
442              
443             #-----------------------------------------------
444             #-----------------------------------------------
445             # Begin exported subroutines.
446             #-----------------------------------------------
447             #-----------------------------------------------
448              
449              
450              
451              
452              
453             =head2 votefair_read_calculate_write
454              
455             Reads numbers from the standard input file, does all
456             the requested calculations, and writes requested
457             results to the standard output file. In most
458             election situations this is the only subroutine
459             that needs to be used.
460              
461             =cut
462              
463             #-----------------------------------------------
464             #-----------------------------------------------
465             # votefair_read_calculate_write
466             #-----------------------------------------------
467             #-----------------------------------------------
468              
469             sub votefair_read_calculate_write
470             {
471              
472 0     0 1 0 my $input_number_count ;
473             my $input_line ;
474 0         0 my $invalid_characters ;
475 0         0 my $next_number_text ;
476 0         0 my $next_number ;
477 0         0 my $previous_number ;
478 0         0 my $next_result_code ;
479              
480              
481             #-----------------------------------------------
482             # Reset all the values -- in case this
483             # subroutine is used more than once.
484              
485 0 0 0     0 if ( ( $global_begin_module_actions_done != $global_true ) || ( $global_intitialization_done != $global_true ) )
486             {
487 0         0 &do_full_initialization( ) ;
488             }
489              
490              
491             #-----------------------------------------------
492             # Read each line from the standard
493             # input file.
494              
495 0         0 $global_case_specific_warning_begin = "case-" . "0" . "-warning-message:\n" . "word-case-capitalized " . "0" ;
496 0         0 $previous_number = 0 ;
497 0         0 $global_case_number = 0 ;
498 0         0 $global_true_or_false_ignore_case[ $global_case_number ] = $global_false ;
499 0         0 $input_number_count = 0 ;
500 0         0 while( $input_line = )
501             {
502 0         0 chomp( $input_line ) ;
503 0         0 $input_line =~ s/[\n\t]/ /sg ;
504              
505              
506             #-----------------------------------------------
507             # If any non-numeric text is encountered,
508             # ignore it, indicate a warning, and ignore the
509             # entire case in which it occurs.
510              
511 0         0 while ( $input_line =~ /^(.*?)(([^ \-0-9]+)([^ 0-9]*)([^ \-0-9]+))(.*)$/s )
512             {
513 0         0 $invalid_characters = $2 ;
514 0         0 $input_line = $1 . " " . $6 ;
515 0         0 $global_output_warning_messages_case_or_question_specific .= $global_case_specific_warning_begin . " contains-non-numeric-characters (" . $invalid_characters . ")" . "\n-----\n\n" ;
516 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[Warning: Input line contains non-numeric characters (" . $invalid_characters . "), so this case (" . $global_case_number . ") will be ignored]\n" } ;
  0         0  
517 0         0 $global_true_or_false_ignore_case[ $global_case_number ] = $global_true ;
518             }
519              
520              
521             #-----------------------------------------------
522             # Get each number from the line, and put each
523             # number into the input array. The negative
524             # numbers have the meanings that are declared
525             # earlier in this module. When a new case
526             # starts, update the case number.
527              
528 0         0 while ( $input_line =~ /^[^\-0-9]*(\-?[0-9]+)(.*)$/s )
529             {
530 0         0 $next_number_text = $1 ;
531 0         0 $input_line = $2 ;
532 0         0 $next_number = $next_number_text + 0 ;
533 0         0 $global_possible_error_message = &votefair_put_next_vote_info_number( $next_number ) ;
534 0 0       0 if ( $global_possible_error_message ne "" )
535             {
536 0         0 last ;
537             }
538 0         0 $input_number_count ++ ;
539 0 0       0 if ( $previous_number == $global_voteinfo_code_for_case_number )
540             {
541 0         0 $global_case_number = $next_number ;
542 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[case number " . $global_case_number . "]\n" } ;
  0         0  
543 0         0 $global_case_specific_warning_begin = "case-" . $global_case_number . "-warning-message:\n" . "word-case-capitalized " . $global_case_number ;
544             }
545 0         0 $previous_number = $next_number ;
546             }
547              
548              
549             #-----------------------------------------------
550             # If the current line contains a number that
551             # produces an error, exit the main loop.
552              
553 0 0       0 if ( $global_possible_error_message ne "" )
554             {
555 0         0 last ;
556             }
557              
558              
559             #-----------------------------------------------
560             # Repeat the loop to handle the next input line.
561              
562             }
563              
564              
565             #-----------------------------------------------
566             # If less than two numbers were found, indicate
567             # this no-data error.
568              
569 0 0       0 if ( $input_number_count < 2 )
570             {
571 0         0 $global_possible_error_message = "Error: Input file does not contain any data." ;
572 0         0 $global_length_of_result_info_list = 0 ;
573 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[Error: Input file does not contain any data]\n" } ;
  0         0  
574             }
575              
576              
577             #-----------------------------------------------
578             # Do the calculations, after first checking
579             # the input numbers for validity.
580              
581 0 0       0 if ( $global_possible_error_message eq "" )
582             {
583 0         0 $global_possible_error_message = &votefair_do_calculations_all_questions( ) ;
584             }
585              
586              
587             #-----------------------------------------------
588             # If any errors or warnings were encountered,
589             # write the messages as Dashrep definitions.
590              
591 0         0 open ( MSGFILE , ">" . $global_error_message_filename ) ;
592 0         0 print MSGFILE "dashrep-definitions-begin\n\n" ;
593 0 0       0 if ( $global_possible_error_message =~ /[^ ]/ )
594             {
595 0         0 print MSGFILE "*----- Error message -----*\n\n\n" . "output-error-message:\n" . $global_possible_error_message . "\n" . "-----\n\n" ;
596             } else
597             {
598 0         0 print MSGFILE "*----- All OK, no error message -----*\n\n\n" . "output-error-message:\n" . "-----\n\n" ;
599             }
600 0         0 print MSGFILE "output-warning-message:\n" . $global_output_warning_message . "\n" . "-----\n\n" ;
601              
602 0         0 print MSGFILE $global_output_warning_messages_case_or_question_specific . "\n" . "dashrep-definitions-end\n" ;
603 0         0 close MSGFILE ;
604              
605              
606             #-----------------------------------------------
607             # If there was an error, exit this subroutine.
608              
609 0 0       0 if ( $global_possible_error_message ne "" )
610             {
611 0         0 print $global_possible_error_message . "\n\n\n\n" ;
612 0         0 print LOGOUT "Error encountered; see main output file (or file " . $global_error_message_filename . " or file " . $global_log_filename . ") for details" . "\n\n" ;
613 0         0 return 0 ;
614             } else
615             {
616 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[all done, no major error encountered]\n\n" } ;
  0         0  
617             }
618              
619              
620             #-----------------------------------------------
621             # Write the result code numbers to the standard
622             # output file.
623              
624 0 0       0 if ( $global_length_of_result_info_list < 2 )
625             {
626 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[no results calculated]" . "\n\n" } ;
  0         0  
627             } else
628             {
629 0         0 $global_pointer_to_output_results = 0 ;
630 0         0 $next_result_code = &votefair_get_next_result_info_number( ) ;
631             # if ( $global_logging_info == $global_true ) { print LOGOUT "[out: " . $next_result_code . "]" } ;
632 0         0 while ( $next_result_code != $global_voteinfo_code_for_end_of_all_cases )
633             {
634 0 0       0 if ( $next_result_code == 0 )
    0          
635             {
636 0         0 print "0" . "\n" ;
637             } elsif ( $next_result_code > 0 )
638             {
639 0         0 print sprintf( "%d" , $next_result_code ) . "\n" ;
640             } else
641             {
642 0 0       0 if ( $global_true_or_false_request_dashrep_phrases_in_output == $global_true )
643             {
644 0         0 print "voteinfo-inverse-" . sprintf( "%d" , -( $next_result_code ) ) . "-code" . "\n" ;
645             } else
646             {
647 0         0 print sprintf( "%d" , $next_result_code ) . "\n" ;
648             }
649             }
650 0         0 $next_result_code = &votefair_get_next_result_info_number( ) ;
651             # if ( $global_logging_info == $global_true ) { print LOGOUT "[out: " . $next_result_code . "]" } ;
652             }
653             }
654              
655              
656             #-----------------------------------------------
657             # End of subroutine.
658              
659 0         0 return 1 ;
660              
661             }
662              
663              
664              
665              
666             =head2 votefair_put_next_vote_info_number
667              
668             Adds the next input vote-info number to the list
669             that stores the input data.
670             The meaning of the negative numbers are explained
671             in an output file that this module creates.
672              
673             =cut
674              
675             #-----------------------------------------------
676             #-----------------------------------------------
677             # votefair_put_next_vote_info_number
678             #-----------------------------------------------
679             #-----------------------------------------------
680              
681             sub votefair_put_next_vote_info_number
682             {
683              
684 0     0 1 0 my $current_vote_info_number = 0 ;
685              
686              
687              
688             #-----------------------------------------------
689             # If initialization has not yet been done, do it.
690              
691 0 0 0     0 if ( ( $global_begin_module_actions_done != $global_true ) || ( $global_intitialization_done != $global_true ) )
692             {
693 0         0 &do_full_initialization( ) ;
694             }
695              
696              
697             #-----------------------------------------------
698             # Get the next vote-info number.
699              
700 0 0       0 if ( scalar( @_ ) == 1 )
701             {
702 0 0       0 if ( defined( $_[ 0 ] ) )
703             {
704 0         0 $current_vote_info_number = $_[ 0 ] ;
705             } else
706             {
707 0         0 warn "Error: Call to votefair_put_next_vote_info_number subroutine does not supply a parameter." ;
708 0         0 return "error-no-parameter-supplied" ;
709             }
710             } else
711             {
712 0         0 warn "Error: Call to votefair_put_next_vote_info_number subroutine does not have exactly one parameter." ;
713 0         0 return "error-not-exactly-one-parameter" ;
714             }
715              
716              
717             #-----------------------------------------------
718             # Ensure the array has not become too long.
719              
720 0 0       0 if ( $global_length_of_vote_info_list > $global_max_array_length )
721             {
722 0         0 warn "ERROR: Too many vote-info numbers ( " . $global_length_of_vote_info_list . ") supplied to votefair_put_next_vote_info_number subroutine." ;
723 0         0 return "Error: Input file containing vote-info numbers is too long (" . $global_length_of_vote_info_list . ")" ;
724             }
725              
726              
727             #-----------------------------------------------
728             # Store the supplied vote-info number.
729              
730 0         0 $global_vote_info_list[ $global_length_of_vote_info_list ] = $current_vote_info_number ;
731             # if ( $global_logging_info == $global_true ) { print LOGOUT "[" . $current_vote_info_number . "]" } ;
732              
733              
734             #-----------------------------------------------
735             # Increment the list pointer.
736              
737 0         0 $global_length_of_vote_info_list ++ ;
738              
739              
740             #-----------------------------------------------
741             # Insert an end-of-info code number at the next
742             # position, in case this is the last vote-info
743             # number put into the list.
744              
745 0         0 $global_vote_info_list[ $global_length_of_vote_info_list ] = $global_voteinfo_code_for_end_of_all_cases ;
746              
747              
748             #-----------------------------------------------
749             # End of subroutine.
750              
751 0         0 return "" ;
752              
753             }
754              
755              
756              
757              
758             =head2 votefair_get_next_result_info_number
759              
760             Gets the next result-info number from the list
761             that stores the result information.
762              
763             =cut
764              
765             #-----------------------------------------------
766             #-----------------------------------------------
767             # votefair_get_next_result_info_number
768             #-----------------------------------------------
769             #-----------------------------------------------
770              
771             sub votefair_get_next_result_info_number
772             {
773              
774 0     0 1 0 my $current_result_info_number ;
775              
776              
777             #-----------------------------------------------
778             # If initialization has not yet been done,
779             # indicate a major error because the user has
780             # not yet supplied any input data.
781              
782 0 0 0     0 if ( ( $global_begin_module_actions_done != $global_true ) || ( $global_intitialization_done != $global_true ) )
783             {
784 0         0 warn "ERROR: Input data must be supplied (and calculations done) before the votefair_get_next_result_info_number subroutine is called." ;
785             }
786              
787              
788             #-----------------------------------------------
789             # If the end of the list has been reached,
790             # return the code that indicates the end
791             # of the results.
792              
793 0 0 0     0 if ( ( $global_pointer_to_output_results >= $global_length_of_result_info_list ) || ( $global_pointer_to_output_results >= $global_max_array_length ) )
794             {
795 0         0 return $global_voteinfo_code_for_end_of_all_cases ;
796             }
797              
798              
799             #-----------------------------------------------
800             # If the pointer is negative, point to the
801             # first item.
802              
803 0 0       0 if ( $global_pointer_to_output_results < 0 )
804             {
805 0         0 $global_pointer_to_output_results = 0 ;
806             }
807              
808              
809             #-----------------------------------------------
810             # If the stored value in the list is not
811             # defined, indicate the end of the results.
812              
813 0 0       0 if ( not( defined( $global_output_results[ $global_pointer_to_output_results ] ) ) )
814             {
815 0         0 return $global_voteinfo_code_for_end_of_all_cases ;
816             }
817              
818              
819             #-----------------------------------------------
820             # Get the next result-info number.
821              
822 0         0 $current_result_info_number = $global_output_results[ $global_pointer_to_output_results ] ;
823             # if ( $global_logging_info == $global_true ) { print LOGOUT "[" . $current_result_info_number . "]" } ;
824              
825              
826             #-----------------------------------------------
827             # If the end-of-all-cases code is encountered,
828             # return with that value -- without changing
829             # the pointer.
830              
831 0 0       0 if ( $current_result_info_number == $global_voteinfo_code_for_end_of_all_cases )
832             {
833 0         0 return $global_voteinfo_code_for_end_of_all_cases ;
834             }
835              
836              
837             #-----------------------------------------------
838             # Increment the list pointer.
839              
840 0         0 $global_pointer_to_output_results ++ ;
841              
842              
843             #-----------------------------------------------
844             # Return the value.
845              
846 0         0 return $current_result_info_number ;
847              
848              
849             #-----------------------------------------------
850             # End of subroutine.
851              
852             }
853              
854              
855              
856              
857             =head2 votefair_put_input_string
858              
859             Interprets an input text string that contains
860             vote-info data (for all cases). Unlike the
861             votefair_put_next_vote_info_number
862             subroutine, this string can contain easy-to-type
863             codes instead of numeric-only codes.
864             These codes are useful for testing this module,
865             and for supplying a hypothetical voting scenario
866             that is typed rather than collected through
867             ballots.
868              
869             =cut
870              
871             #-----------------------------------------------
872             #-----------------------------------------------
873             # votefair_put_input_string
874             #-----------------------------------------------
875             #-----------------------------------------------
876              
877             sub votefair_put_input_string
878             {
879 17     17 1 4135 my $current_vote_info_code ;
880             my $current_vote_info_number ;
881 0         0 my $partial_supplied_vote_info_text ;
882              
883              
884             #-----------------------------------------------
885             # If initialization has not yet been done, do it.
886              
887 17 50 66     109 if ( ( $global_begin_module_actions_done != $global_true ) || ( $global_intitialization_done != $global_true ) )
888             {
889 17         61 &do_full_initialization( ) ;
890             }
891              
892              
893             #-----------------------------------------------
894             # Get the text string.
895              
896 17         32 $global_supplied_vote_info_text = "" ;
897 17 50       45 if ( scalar( @_ ) == 1 )
898             {
899 17 50       41 if ( defined( $_[ 0 ] ) )
900             {
901 17         27 $global_supplied_vote_info_text = $_[ 0 ] ;
902             }
903             }
904 17 50       40 if ( $global_logging_info == $global_true ) { print LOGOUT "\n[vote info: " . $global_supplied_vote_info_text . "]\n\n" } ;
  17         58  
905              
906              
907             #-----------------------------------------------
908             # Get each vote-info number or code, and write
909             # it to the end of the vote-info input list.
910              
911 17         28 $partial_supplied_vote_info_text = $global_supplied_vote_info_text ;
912 17         116 while ( $partial_supplied_vote_info_text =~ /^ *([^ ]+) *(.*)$/s )
913             {
914 849         1264 $current_vote_info_code = $1 ;
915 849         1286 $partial_supplied_vote_info_text = $2 ;
916 849         1002 $current_vote_info_code =~ s/ +//g ;
917              
918              
919             #-----------------------------------------------
920             # Ensure the array has not become too long.
921              
922 849 50       1587 if ( $global_length_of_vote_info_list > $global_max_array_length )
923             {
924 0         0 warn "ERROR: Too many vote-info numbers ( " . $global_length_of_vote_info_list . ") supplied to votefair_put_next_vote_info_number subroutine." ;
925 0         0 return "Error: Input file containing vote-info numbers is too long (" . $global_length_of_vote_info_list . ")" ;
926             }
927              
928              
929             #-----------------------------------------------
930             # Convert the code (which might be text digits)
931             # into a vote-info number.
932              
933 849 100       2401 if ( $current_vote_info_code =~ /^[0-9\-]+$/ )
    50          
934             {
935 557         738 $current_vote_info_number = $current_vote_info_code + 0 ;
936             } elsif ( defined( $global_code_number_for_letters{ $current_vote_info_code } ) )
937             {
938 292         445 $current_vote_info_number = $global_code_number_for_letters{ $current_vote_info_code } ;
939             }
940              
941              
942             #-----------------------------------------------
943             # Store the supplied vote-info number.
944              
945 849         1229 $global_vote_info_list[ $global_length_of_vote_info_list ] = $current_vote_info_number ;
946              
947              
948             #-----------------------------------------------
949             # Increment the list pointer.
950              
951 849         2919 $global_length_of_vote_info_list ++ ;
952              
953              
954             #-----------------------------------------------
955             # Repeat the loop to handle the next vote-info
956             # code in the string.
957              
958             }
959              
960              
961             #-----------------------------------------------
962             # Insert an end-of-info code number at the next
963             # position, in case this is the last vote info
964             # put into the list.
965              
966 17         26 $global_vote_info_list[ $global_length_of_vote_info_list ] = $global_voteinfo_code_for_end_of_all_cases ;
967 17         28 $global_length_of_vote_info_list ++ ;
968              
969              
970             #-----------------------------------------------
971             # End of subroutine.
972              
973 17         50 return "" ;
974              
975              
976             }
977              
978              
979              
980              
981             =head2 votefair_get_output_string
982              
983             Creates a text string that contains all the
984             results in a person-readable code.
985             It is useful for testing this module, and to
986             allow a person to directly (although cryptically)
987             read the results.
988              
989             =cut
990              
991             #-----------------------------------------------
992             #-----------------------------------------------
993             # votefair_get_output_string
994             #-----------------------------------------------
995             #-----------------------------------------------
996              
997             sub votefair_get_output_string
998             {
999              
1000 17     17 1 123 my $current_result_info_number ;
1001             my $letters ;
1002 0         0 my $result_info ;
1003 0         0 my @letters_for_negative_of_code_number ;
1004              
1005              
1006             #-----------------------------------------------
1007             # If initialization has not yet been done,
1008             # indicate a major error because the user has
1009             # not yet supplied any input data.
1010              
1011 17 50 33     90 if ( ( $global_begin_module_actions_done != $global_true ) || ( $global_intitialization_done != $global_true ) )
1012             {
1013 0         0 warn "ERROR: Input data must be supplied (and calculations done) before the votefair_get_output_string subroutine is called." ;
1014             }
1015              
1016              
1017             #-----------------------------------------------
1018             # Create the list of valid letter codes that is
1019             # indexed by the negative code number.
1020              
1021 17         320 foreach $letters ( keys( %global_code_number_for_letters ) )
1022             {
1023 799         1419 $letters_for_negative_of_code_number[ - ( $global_code_number_for_letters{ $letters } ) ] = $letters ;
1024             }
1025              
1026              
1027             #-----------------------------------------------
1028             # Point to the beginning of the output list.
1029              
1030 17         72 $global_pointer_to_output_results = 0 ;
1031 17 50       49 if ( $global_logging_info == $global_true ) { print LOGOUT "[get output string, length of output list is " . $global_length_of_result_info_list . "]\n" } ;
  17         42  
1032              
1033              
1034             #-----------------------------------------------
1035             # Begin a loop that repeats for each result
1036             # number, stopping at the end of the results.
1037              
1038 17   33     160 while ( ( $global_pointer_to_output_results < $global_length_of_result_info_list ) && ( $global_pointer_to_output_results <= $global_max_array_length ) )
1039             {
1040              
1041              
1042             #-----------------------------------------------
1043             # If the stored value in the list is not
1044             # defined, indicate the end of the results.
1045              
1046 2682 50       5526 if ( not( defined( $global_output_results[ $global_pointer_to_output_results ] ) ) )
1047             {
1048 0         0 $result_info .= "undefined-result-code-number" ;
1049 0         0 last ;
1050             }
1051              
1052              
1053             #-----------------------------------------------
1054             # Get the next result-info number.
1055              
1056 2682         2791 $current_result_info_number = $global_output_results[ $global_pointer_to_output_results ] ;
1057              
1058              
1059             #-----------------------------------------------
1060             # If the result number is negative, convert it
1061             # into the letters that are associated with that
1062             # code number.
1063             # If the number is positive, convert it to a
1064             # text version of that number.
1065             # Append the resulting text to the end of the
1066             # results string.
1067              
1068 2682 100       4578 if ( $current_result_info_number < 0 )
    100          
1069             {
1070 1558 50       2392 if ( defined( $letters_for_negative_of_code_number[ - ( $current_result_info_number ) ] ) )
1071             {
1072 1558         2394 $result_info .= $letters_for_negative_of_code_number[ - ( $current_result_info_number ) ] . " " ;
1073             } else
1074             {
1075 0         0 $result_info .= "undefined-code-number-negative-" . sprintf( "%d" , - ( $current_result_info_number ) ) ;
1076             }
1077             } elsif ( $current_result_info_number == 0 )
1078             {
1079 67         85 $result_info .= "0 " ;
1080             } else
1081             {
1082 1057         1977 $result_info .= sprintf( "%d" , $current_result_info_number ) . " " ;
1083             }
1084              
1085              
1086             #-----------------------------------------------
1087             # When the end-of-all-cases code is encountered,
1088             # exit the loop.
1089              
1090 2682 100       5070 if ( $current_result_info_number == $global_voteinfo_code_for_end_of_all_cases )
1091             {
1092 17         27 last ;
1093             }
1094              
1095              
1096             #-----------------------------------------------
1097             # Increment the list pointer.
1098              
1099 2665         10422 $global_pointer_to_output_results ++ ;
1100              
1101              
1102             #-----------------------------------------------
1103             # Repeat the loop that gets each result
1104             # number.
1105              
1106             }
1107              
1108              
1109             #-----------------------------------------------
1110             # Allow only one space between items, and
1111             # remove leading and trailing spaces (so that
1112             # these results can be used for testing).
1113              
1114 17         48 $result_info =~ s/^ +// ;
1115 17         523 $result_info =~ s/ +$//s ;
1116 17         64 $result_info =~ s/ +/ /gs ;
1117              
1118              
1119             #-----------------------------------------------
1120             # Return the results.
1121              
1122 17 50       41 if ( $global_logging_info == $global_true ) { print LOGOUT "\n[vote info: " . $global_supplied_vote_info_text . "]\n\n" } ;
  17         67  
1123 17 50       47 if ( $global_logging_info == $global_true ) { print LOGOUT "\n[results string: " . $result_info . "]\n\n" } ;
  17         109  
1124 17         124 return $result_info ;
1125              
1126              
1127             #-----------------------------------------------
1128             # Point to the first item in the results list
1129             # in case the results are also accessed by
1130             # using the votefair_get_next_result_info_number
1131             # subroutine.
1132              
1133 0         0 $global_pointer_to_output_results = 0 ;
1134              
1135              
1136             #-----------------------------------------------
1137             # End of subroutine.
1138              
1139             }
1140              
1141              
1142              
1143              
1144             =head2 votefair_do_calculations_all_questions
1145              
1146             Does the requested calculations for all the
1147             questions (although other subroutines do the
1148             actual calculations).
1149              
1150             =cut
1151              
1152             #-----------------------------------------------
1153             #-----------------------------------------------
1154             # votefair_do_calculations_all_questions
1155             #-----------------------------------------------
1156             #-----------------------------------------------
1157              
1158             sub votefair_do_calculations_all_questions
1159             {
1160              
1161              
1162              
1163             #-----------------------------------------------
1164             # If initialization has not yet been done,
1165             # indicate a major error because the user has
1166             # not yet supplied any input data.
1167              
1168 17 50 33 17 1 300 if ( ( $global_begin_module_actions_done != $global_true ) || ( $global_intitialization_done != $global_true ) )
1169             {
1170 0         0 warn "ERROR: Input data must be supplied before the votefair_do_calculations_all_questions subroutine is called." ;
1171             }
1172              
1173              
1174             #-----------------------------------------------
1175             # Clear the output list.
1176              
1177 17         31 $global_pointer_to_output_results = 0 ;
1178 17         29 @global_output_results = ( ) ;
1179 17         32 $global_output_results[ $global_pointer_to_output_results ] = $global_voteinfo_code_for_end_of_all_cases ;
1180 17         22 $global_pointer_to_output_results = 0 ;
1181              
1182              
1183             #-----------------------------------------------
1184             # Check for errors in the vote-info number list,
1185             # and get some needed values such as the number
1186             # of questions in each case, the number of
1187             # choices in each question, and requests that
1188             # apply to all the cases. Also, determine
1189             # which cases, if any, need to be skipped
1190             # because they contain invalid vote-info
1191             # numbers.
1192              
1193 17         46 $global_possible_error_message = &check_vote_info_numbers( ) ;
1194 17 50       50 if ( $global_possible_error_message ne "" )
1195             {
1196 0         0 return "ERROR: Error in vote-info number list: " . $global_possible_error_message . "\n" ;
1197             }
1198              
1199              
1200             #-----------------------------------------------
1201             # Begin a loop that handles each case.
1202             #
1203             # Each case may involve voters and questions
1204             # that are unrelated to any other case.
1205             # The questions within the same case must
1206             # be questions that were on the same ballot and
1207             # voted on by the same people.
1208             #
1209             # When all the cases have been handled, exit
1210             # the loop.
1211              
1212 17         24 $global_input_pointer_start_next_case = 0 ;
1213 17 50       37 if ( $global_logging_info == $global_true ) { print LOGOUT "[all questions, beginning loop that handles each case]" } ;
  17         30  
1214 17   66     83 while ( ( $global_input_pointer_start_next_case < $global_max_array_length ) && ( $global_vote_info_list[ $global_input_pointer_start_next_case ] != $global_voteinfo_code_for_end_of_all_cases ) )
1215             {
1216             # if ( $global_logging_info == $global_true ) { print LOGOUT "[all questions, pointer: " . $global_input_pointer_start_next_case . " , value: " . $global_vote_info_list[ $global_input_pointer_start_next_case ] . "]\n" } ;
1217              
1218 731 100       1302 if ( $global_vote_info_list[ $global_input_pointer_start_next_case ] != $global_voteinfo_code_for_case_number )
1219             {
1220 711         599 $global_input_pointer_start_next_case ++ ;
1221 711         2725 next ;
1222             }
1223 20         26 $global_input_pointer_start_next_case ++ ;
1224 20         28 $global_case_number = $global_vote_info_list[ $global_input_pointer_start_next_case ] ;
1225 20 50       45 if ( $global_logging_info == $global_true ) { print LOGOUT "\n[case " . $global_case_number . "]" } ;
  20         53  
1226 20         20 $global_input_pointer_start_next_case ++ ;
1227              
1228              
1229             #-----------------------------------------------
1230             # Indicate the case number in the results list.
1231              
1232 20         49 &put_next_result_info_number( $global_voteinfo_code_for_case_number ) ;
1233 20         37 &put_next_result_info_number( $global_case_number ) ;
1234              
1235              
1236             #-----------------------------------------------
1237             # If the vote-info numbers for this case were
1238             # invalid, skip this case.
1239              
1240              
1241             # if ( $global_case_number > 40 )
1242             # {
1243             # $global_true_or_false_ignore_case[ $global_case_number ] = $global_true ;
1244             # }
1245              
1246              
1247 20 100       56 if ( $global_true_or_false_ignore_case[ $global_case_number ] == $global_true )
1248             {
1249 2         23 &put_next_result_info_number( $global_voteinfo_code_for_skip_case ) ;
1250 2 50       7 if ( $global_logging_info == $global_true ) { print LOGOUT "[all questions, case " . $global_case_number . " skipped because errors were found in the vote-info numbers]\n" } ;
  2         6  
1251 2   66     19 while ( ( $global_vote_info_list[ $global_input_pointer_start_next_case ] != $global_voteinfo_code_for_case_number ) && ( $global_vote_info_list[ $global_input_pointer_start_next_case ] != $global_voteinfo_code_for_end_of_all_cases ) && ( $global_input_pointer_start_next_case < $global_max_array_length ) )
      66        
1252             {
1253 18         97 $global_input_pointer_start_next_case ++ ;
1254             }
1255 2         11 next ;
1256             }
1257              
1258             #-----------------------------------------------
1259             # If there are no questions in this case,
1260             # indicate it, and then restart the main loop.
1261             # If this error condition applies, it has
1262             # already been indicated in the output
1263             # warning messages.
1264              
1265 18 50       50 if ( $global_question_count_for_case[ $global_case_number ] < 1 )
1266             {
1267 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[all questions, warning: case " . $global_case_number . " does not contain any questions]\n" } ;
  0         0  
1268 0         0 next ;
1269             }
1270              
1271              
1272             #-----------------------------------------------
1273             # Begin a loop that handles each question
1274             # (within a case).
1275             # Question numbers are sequential (i.e. no
1276             # question numbers are skipped).
1277              
1278 18 50       38 if ( $global_logging_info == $global_true ) { print LOGOUT "\n[all questions, case " . $global_case_number . ", has " . $global_question_count_for_case[ $global_case_number ] . " questions]\n" } ;
  18         61  
1279 18         53 for ( $global_question_number = 1 ; $global_question_number <= $global_question_count_for_case[ $global_case_number ] ; $global_question_number ++ )
1280             {
1281              
1282              
1283             #-----------------------------------------------
1284             # Indicate the question number in the results list.
1285              
1286 19         44 &put_next_result_info_number( $global_voteinfo_code_for_question_number ) ;
1287 19         35 &put_next_result_info_number( $global_question_number ) ;
1288 19 50       48 if ( $global_logging_info == $global_true ) { print LOGOUT "\n[all questions, case " . $global_case_number . ", question " . $global_question_number . "]\n" } ;
  19         56  
1289              
1290              
1291             #-----------------------------------------------
1292             # Get the number of choices for this question.
1293              
1294 19         45 $global_full_choice_count = $global_choice_count_for_case_and_question[ $global_case_number ][ $global_question_number ] ;
1295 19 50       49 if ( $global_logging_info == $global_true ) { print LOGOUT "[all questions, actual choice count = " . $global_full_choice_count . "]" } ;
  19         46  
1296              
1297              
1298             #-----------------------------------------------
1299             # Do the calculations for this question.
1300              
1301 19         52 &calculate_results_for_one_question( ) ;
1302              
1303              
1304             #-----------------------------------------------
1305             # Write the total ballot count (for cross-checking
1306             # purposes).
1307              
1308 19         47 &put_next_result_info_number( $global_voteinfo_code_for_total_ballot_count ) ;
1309 19         42 &put_next_result_info_number( $global_current_total_vote_count ) ;
1310              
1311              
1312             #-----------------------------------------------
1313             # Repeat the loop that handles the next question
1314             # (within a case).
1315              
1316 19 50       51 if ( $global_logging_info == $global_true ) { print LOGOUT "[all questions, this question done, repeating loop for next question]\n" } ;
  19         94  
1317             }
1318              
1319              
1320             #-----------------------------------------------
1321             # Repeat the loop that handles the next case.
1322              
1323 18 50       47 if ( $global_logging_info == $global_true ) { print LOGOUT "[all questions, all questions done, repeating loop for next case]\n" } ;
  18         235  
1324             }
1325              
1326              
1327             #-----------------------------------------------
1328             # Terminate the results list.
1329              
1330 17         37 &put_next_result_info_number( $global_voteinfo_code_for_end_of_all_cases ) ;
1331 17 50       40 if ( $global_logging_info == $global_true ) { print LOGOUT "[all questions, all cases done]\n" } ;
  17         30  
1332              
1333              
1334             #-----------------------------------------------
1335             # Save the result-info list pointer as the
1336             # length of the portion of the result-info
1337             # list that contains results.
1338             # Then reset the pointer to the
1339             # beginning of the list.
1340              
1341 17         23 $global_length_of_result_info_list = $global_pointer_to_output_results + 1 ;
1342 17         32 $global_pointer_to_output_results = 0 ;
1343 17 50       44 if ( $global_logging_info == $global_true ) { print LOGOUT "[all questions, length of output list is " . $global_length_of_result_info_list . "]\n" } ;
  17         46  
1344              
1345              
1346             #-----------------------------------------------
1347             # End of subroutine.
1348              
1349 17 50       46 if ( $global_logging_info == $global_true ) { print LOGOUT "[all questions, exiting subroutine]\n" } ;
  17         82  
1350 17         92 return "" ;
1351              
1352             }
1353              
1354              
1355              
1356              
1357             =head2 votefair_start_new_cases
1358              
1359             Does initialization again so that another batch of
1360             cases of data can be processed. Normally this
1361             subroutine is not needed because all the cases
1362             (each with independent questions and preferences)
1363             are done in one batch.
1364              
1365             =cut
1366              
1367             #-----------------------------------------------
1368             #-----------------------------------------------
1369             # votefair_start_new_cases
1370             #-----------------------------------------------
1371             #-----------------------------------------------
1372              
1373             sub votefair_start_new_cases
1374             {
1375              
1376              
1377             #-----------------------------------------------
1378             # Request that initialization be done again.
1379             # Do not actually do the initialization until
1380             # it is needed, in case this subroutine is
1381             # used unnecessarily.
1382              
1383 16     16 1 619 $global_intitialization_done = $global_false ;
1384 16 50       51 if ( $global_logging_info == $global_true ) { print LOGOUT "[requested doing full initialization]\n" } ;
  16         43  
1385              
1386              
1387             #-----------------------------------------------
1388             # End of subroutine.
1389              
1390             }
1391              
1392              
1393              
1394              
1395              
1396             =head2 votefair_always_do_rep_and_party_ranking
1397              
1398             Requests that VoteFair representation ranking and
1399             VoteFair party ranking always be done -- except
1400             when only plurality votes are requested (because
1401             in those cases 1-2-3 ballots have not been used).
1402              
1403             =cut
1404              
1405             #-----------------------------------------------
1406             #-----------------------------------------------
1407             # votefair_always_do_rep_and_party_ranking
1408             #-----------------------------------------------
1409             #-----------------------------------------------
1410              
1411             sub votefair_always_do_rep_and_party_ranking
1412             {
1413              
1414              
1415             #-----------------------------------------------
1416             # If initialization has not yet been done, do it.
1417              
1418 0 0 0 0 1 0 if ( ( $global_begin_module_actions_done != $global_true ) || ( $global_intitialization_done != $global_true ) )
1419             {
1420 0         0 &do_full_initialization( ) ;
1421             }
1422              
1423              
1424             #-----------------------------------------------
1425             # Request that VoteFair representation ranking
1426             # and VoteFair party ranking always be done.
1427              
1428 0         0 $global_true_or_false_always_request_only_plurality_results = $global_false ;
1429 0         0 $global_true_or_false_always_request_votefair_representation_rank = $global_true ;
1430 0         0 $global_true_or_false_always_request_votefair_party_rank = $global_true ;
1431              
1432              
1433             #-----------------------------------------------
1434             # Subroutine done.
1435              
1436 0         0 return ;
1437              
1438             }
1439              
1440              
1441              
1442              
1443             #-----------------------------------------------
1444             #-----------------------------------------------
1445             # Begin non-exported subroutines.
1446             #-----------------------------------------------
1447             #-----------------------------------------------
1448              
1449              
1450              
1451              
1452              
1453             =head2 calc_votefair_popularity_rank
1454              
1455             (Not exported, for internal use only.)
1456              
1457             Handles the overhead actions for calculating
1458             VoteFair popularity ranking results, as
1459             described in the book "Ending The Hidden
1460             Unfairness In U.S. Elections", and as
1461             described in Wikipedia as the "Condorcet-Kemeny
1462             method" (which redirects to the "Kemeny-Young
1463             method" article). See VoteFair.org for details.
1464              
1465             These results are used in situations where
1466             a single seat is being filled (and there is
1467             only one such seat), or to determine the full
1468             ranking of choices, or to correctly identify
1469             the least-popular choice (where that choice
1470             is a contestant who is eliminated before the
1471             next round of the contest).
1472              
1473             =cut
1474              
1475             #-----------------------------------------------
1476             #-----------------------------------------------
1477             # calc_votefair_popularity_rank
1478             #-----------------------------------------------
1479             #-----------------------------------------------
1480              
1481             sub calc_votefair_popularity_rank
1482             {
1483              
1484 84     84 1 137 my $actual_choice ;
1485             my $adjusted_choice ;
1486 0         0 my $ranking_level ;
1487 0         0 my $twice_highest_possible_score ;
1488 0         0 my $ranking_level_from_all_scores_calc ;
1489              
1490              
1491             #-----------------------------------------------
1492             # Initialize the result rankings -- to zeros, which
1493             # indicate that no ranking has been done.
1494              
1495 84         304 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
1496             {
1497 475         513 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
1498 475 50       858 if ( $global_using_choice[ $actual_choice ] == $global_true )
1499             {
1500 475         1078 $global_popularity_ranking_for_actual_choice[ $actual_choice ] = 0 ;
1501             }
1502             }
1503 84         150 $global_choice_count_at_top_popularity_ranking_level = 0 ;
1504 84         107 $global_actual_choice_at_top_popularity_ranking_level = 0 ;
1505              
1506              
1507             #-----------------------------------------------
1508             # Initialize the insertion-sort rankings to zeros,
1509             # which indicate that no ranking has been done.
1510              
1511 84         244 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
1512             {
1513 475         491 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
1514 475 50       839 if ( $global_using_choice[ $actual_choice ] == $global_true )
1515             {
1516 475         1120 $global_insertion_sort_popularity_rank_for_actual_choice[ $actual_choice ] = 0 ;
1517             }
1518             }
1519              
1520              
1521             #-----------------------------------------------
1522             # If the total of the vote counts is zero,
1523             # there is a code bug, so indicate an error.
1524              
1525 84 50       226 if ( $global_current_total_vote_count <= 0 )
1526             {
1527 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[popularity rank, zero counts on ballots]\n" } ;
  0         0  
1528 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[popularity rank, Error: Case " . $global_case_number . " has triggered a program bug caused by a failure to check for zero vote counts]\n" } ;
  0         0  
1529 0         0 $global_possible_error_message .= "Error: Case " . $global_case_number . " has triggered a program bug caused by a failure to check for zero vote counts. " ;
1530 0         0 return ;
1531             }
1532              
1533              
1534             #-----------------------------------------------
1535             # If there are not at least two choices,
1536             # indicate an error and return.
1537              
1538 84 50       224 if ( $global_adjusted_choice_count < 2 )
1539             {
1540 0         0 $global_output_warning_messages_case_or_question_specific .= $global_question_specific_warning_begin . " does-not-have-at-least-two-choices-so-VoteFair-popularity-ranking-cannot-be-done" . "\n-----\n\n" ;
1541 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[popularity rank, ERROR: number of (adjusted) choices is less than two]\n" } ;
  0         0  
1542 0         0 return ;
1543             }
1544              
1545              
1546             #-----------------------------------------------
1547             # Do VoteFair choice-specific pairwise-score
1548             # (CSPS) ranking.
1549              
1550 84 50       168 if ( $global_logging_info == $global_true ) { print LOGOUT "[popularity rank, VoteFair choice-score ranking calculations beginning]\n" } ;
  84         236  
1551 84         286 &calc_votefair_choice_specific_pairwise_score_popularity_rank( ) ;
1552 84 50       260 if ( $global_logging_info == $global_true ) { print LOGOUT "[popularity rank, VoteFair choice-score ranking calculations done]\n" } ;
  84         220  
1553              
1554              
1555             #-----------------------------------------------
1556             # Do VoteFair popularity ranking using the
1557             # insertion-sort method, starting with the
1558             # ranking that was calculated by the
1559             # choice-specific pairwise-score (CSPS)
1560             # method.
1561              
1562 84 50       198 if ( $global_logging_info == $global_true ) { print LOGOUT "[popularity rank, VoteFair insertion-sort popularity ranking calculations beginning]\n" } ;
  84         202  
1563 84         272 &calc_votefair_insertion_sort_popularity_rank( ) ;
1564 84 50       244 if ( $global_logging_info == $global_true ) { print LOGOUT "[popularity rank, VoteFair insertion-sort popularity ranking calculations done]\n" } ;
  84         168  
1565              
1566              
1567             #-----------------------------------------------
1568             # Optionally, in the future, do a cross-check
1569             # that uses the all-scores method to rank the
1570             # top six choices. This cross-check would
1571             # identify theoretically possible situations
1572             # in which the highest-ranked choice is not
1573             # the highest-ranked choice in a sequence that
1574             # has the single (untied) highest sequence
1575             # score. Cases that involve multiple sequences
1576             # with the same highest sequence score are not
1577             # relevant for matching Condorcet-Kemeny
1578             # results because that method does not specify
1579             # how multiple same-highest-score cases should
1580             # be resolved.
1581              
1582              
1583             #-----------------------------------------------
1584             # If there are too many choices, or if there
1585             # are too many ballots that could combine with
1586             # the number of choices to produce an overflow
1587             # in the highest sequence score, skip the
1588             # calculations (done in the next section)
1589             # that check all the sequence scores.
1590              
1591 84         109 $global_check_all_scores_choice_limit = 6 ;
1592 84         118 $global_maximum_twice_highest_possible_score = 900000 ;
1593 84         146 $twice_highest_possible_score = $global_adjusted_choice_count * $global_adjusted_choice_count * $global_current_total_vote_count ;
1594 84 50       194 if ( $global_logging_info == $global_true ) { print LOGOUT "[popularity rank, adjusted choice count is " . $global_adjusted_choice_count . "]\n" } ;
  84         222  
1595 84 50       200 if ( $global_logging_info == $global_true ) { print LOGOUT "[popularity rank, total vote count is " . $global_current_total_vote_count . "]\n" } ;
  84         189  
1596 84 50       274 if ( $global_logging_info == $global_true ) { print LOGOUT "[popularity rank, twice highest possible score is " . $twice_highest_possible_score . "]\n" } ;
  84         235  
1597              
1598 84 100 66     376 if ( ( $global_adjusted_choice_count <= $global_check_all_scores_choice_limit ) && ( $twice_highest_possible_score <= $global_maximum_twice_highest_possible_score ) )
1599             {
1600              
1601              
1602             #-----------------------------------------------
1603             # Do VoteFair popularity ranking calculations
1604             # by calculating all the sequence scores and
1605             # finding the sequence with the highest score.
1606              
1607 56 50       139 if ( $global_logging_info == $global_true ) { print LOGOUT "[popularity rank, calling calc_all_sequence_scores subroutine]\n" } ;
  56         128  
1608 56         146 &calc_all_sequence_scores( ) ;
1609 56 50       141 if ( $global_logging_info == $global_true ) { print LOGOUT "[popularity rank, returned from calc_all_sequence_scores subroutine]\n" } ;
  56         125  
1610             }
1611              
1612              
1613             #-----------------------------------------------
1614             # If the full-score calculations were not done,
1615             # and the insertion-sort calculations were done,
1616             # use the results from the insertion-sort
1617             # calculations.
1618              
1619 84         131 my $ranking_level_from_insertion_sort_calc ;
1620              
1621 84         166 $adjusted_choice = 1 ;
1622 84         140 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
1623 84         147 $ranking_level_from_all_scores_calc = $global_popularity_ranking_for_actual_choice[ $actual_choice ] ;
1624 84 50       227 if ( $global_logging_info == $global_true ) { print LOGOUT "[popularity rank, sample choice " . $actual_choice . " is at popularity level " . $ranking_level_from_all_scores_calc . "]\n" } ;
  84         332  
1625 84         146 $ranking_level_from_insertion_sort_calc = $global_insertion_sort_popularity_rank_for_actual_choice[ $actual_choice ] ;
1626 84 50       212 if ( $global_logging_info == $global_true ) { print LOGOUT "[popularity rank, sample choice " . $actual_choice . " is at insert-sort popularity level " . $ranking_level_from_insertion_sort_calc . "]\n" } ;
  84         320  
1627 84 100 66     426 if ( ( $ranking_level_from_all_scores_calc == 0 ) && ( $ranking_level_from_insertion_sort_calc != 0 ) )
1628             {
1629 28 50       91 if ( $global_logging_info == $global_true ) { print LOGOUT "[popularity rank, using insertion-sort ranking results (because all-score method not done]\n" } ;
  28         166  
1630             {
1631 28         34 $global_sequence_score_using_all_scores_method = 0 ;
  28         60  
1632 28         96 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
1633             {
1634 237         263 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
1635 237         272 $ranking_level = $global_insertion_sort_popularity_rank_for_actual_choice[ $actual_choice ] ;
1636 237         323 $global_popularity_ranking_for_actual_choice[ $actual_choice ] = $ranking_level ;
1637 237 50       429 if ( $global_logging_info == $global_true ) { print LOGOUT "[ choice " . $actual_choice . " is at popularity level " . $ranking_level . "]\n" } ;
  237         734  
1638             }
1639             }
1640             }
1641              
1642              
1643             #-----------------------------------------------
1644             # If the full-score calculations were not done,
1645             # create a warning message that applies to the
1646             # current question, and request only plurality
1647             # counts, and skip over the next section.
1648              
1649 84         166 $adjusted_choice = 1 ;
1650 84         120 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
1651 84 50       220 if ( $global_popularity_ranking_for_actual_choice[ $actual_choice ] == 0 )
1652             {
1653 0         0 $global_output_warning_messages_case_or_question_specific .= $global_question_specific_warning_begin . " has-too-many-choices-so-plurality-counting-done" . "\n-----\n\n" ;
1654 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[popularity rank, Warning: Too many choices (" . $global_adjusted_choice_count . ") for this software version (which handles " . $global_check_all_scores_choice_limit . "), so only plurality results calculated]\n" } ;
  0         0  
1655 0         0 $global_true_or_false_request_only_plurality_results = $global_true ;
1656             } else
1657             {
1658              
1659              
1660             #-----------------------------------------------
1661             # For use by the VoteFair representation
1662             # ranking and VoteFair party ranking
1663             # subroutines, count the number of choices
1664             # that are ranked as most popular.
1665             # If there is just one top-ranked choice,
1666             # make it available as a single value.
1667             # Otherwise set the single value to zero.
1668              
1669 84         116 $adjusted_choice = 1 ;
1670 84         115 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
1671 84 50       201 if ( $global_popularity_ranking_for_actual_choice[ $actual_choice ] > 0 )
1672             {
1673 84         120 $global_choice_count_at_top_popularity_ranking_level = 0 ;
1674 84         99 $global_actual_choice_at_top_popularity_ranking_level = 0 ;
1675 84         212 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
1676             {
1677 475         495 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
1678 475 100       1296 if ( $global_popularity_ranking_for_actual_choice[ $actual_choice ] == 1 )
1679             {
1680 102         123 $global_choice_count_at_top_popularity_ranking_level ++ ;
1681 102 100       197 if ( $global_choice_count_at_top_popularity_ranking_level == 1 )
1682             {
1683 84         100 $global_actual_choice_at_top_popularity_ranking_level = $actual_choice ;
1684             } else
1685             {
1686 18         21 $global_actual_choice_at_top_popularity_ranking_level = 0 ;
1687             }
1688 102 50       217 if ( $global_logging_info == $global_true ) { print LOGOUT "[popularity rank, choice " . $actual_choice . " is at top ranking level]\n" } ;
  102         492  
1689             }
1690             }
1691 84 50       229 if ( $global_logging_info == $global_true ) { print LOGOUT "[popularity rank, count of most-popular choices is " . $global_choice_count_at_top_popularity_ranking_level . "]\n" } ;
  84         236  
1692 84 50       172 if ( $global_logging_info == $global_true ) { print LOGOUT "[popularity rank, if only one top choice, choice number is " . $global_actual_choice_at_top_popularity_ranking_level . "]\n" } ;
  84         242  
1693             }
1694              
1695              
1696             #-----------------------------------------------
1697             # Finish skipping the above section if the
1698             # calculations were not done.
1699              
1700             }
1701              
1702              
1703             #-----------------------------------------------
1704             # Compare the results with other calculation
1705             # methods.
1706              
1707 84         248 &compare_popularity_results( ) ;
1708              
1709              
1710             #-----------------------------------------------
1711             # End of subroutine.
1712              
1713 84 50       202 if ( $global_logging_info == $global_true ) { print LOGOUT "[popularity rank, done calculating VoteFair popularity ranking results for question " . $global_question_number . " in case " . $global_case_number . "]\n" } ;
  84         293  
1714 84         233 return 1 ;
1715              
1716             }
1717              
1718              
1719              
1720              
1721             =head2 calc_votefair_representation_rank
1722              
1723             (Not exported, for internal use only.)
1724              
1725             Calculates VoteFair representation ranking
1726             results, as described in the book "Ending The
1727             Hidden Unfairness In U.S. Elections."
1728             These results are used in situations where
1729             more than one choice is selected, such as
1730             when there is more than one seat being filled,
1731             or when there is more than one activity
1732             (for participation) being offered at the
1733             same time (and attendance at both activities
1734             is not possible).
1735             The first-most representative choice is the most
1736             popular based on VoteFair popularity ranking,
1737             which is calculated before arriving here.
1738             Therefore, this subroutine identifies the
1739             VoteFair-based second-most representative,
1740             third-most representative, etc. choices
1741             in an election.
1742              
1743             =cut
1744              
1745             #-----------------------------------------------
1746             #-----------------------------------------------
1747             # calc_votefair_representation_rank
1748             #-----------------------------------------------
1749             #-----------------------------------------------
1750              
1751             sub calc_votefair_representation_rank
1752             {
1753              
1754 16     16 1 33 my $actual_choice ;
1755             my $adjusted_choice ;
1756 0         0 my $most_preferred_choice ;
1757 0         0 my $previous_most_representative_choice ;
1758 0         0 my $ignored_vote_count ;
1759 0         0 my $non_ignored_vote_count ;
1760 0         0 my $alternative_most_preferred_choice ;
1761 0         0 my $vote_count_for_reduced_influence ;
1762 0         0 my $reduced_influence_amount ;
1763 0         0 my $tie_exists ;
1764 0         0 my $number_of_representation_levels_ranked ;
1765 0         0 my $number_of_choices_rep_ranked ;
1766 0         0 my $single_nonranked_choice ;
1767 0         0 my $initial_choice_count_for_rep_ranking ;
1768 0         0 my $true_or_false_log_details ;
1769              
1770              
1771             #-----------------------------------------------
1772             # Hide or show the details in the log file.
1773              
1774 16         26 $true_or_false_log_details = $global_false ;
1775 16 50       49 if ( $global_logging_info == $global_true )
1776             {
1777 16         36 print LOGOUT "[rep ranking, beginning calc_votefair_representation_rank subroutine]\n\n" ;
1778 16 50       37 if ( $true_or_false_log_details == $global_true )
1779             {
1780 0         0 print LOGOUT "[rep ranking, details shown (change flag value to hide details)]\n" ;
1781             } else
1782             {
1783 16         33 print LOGOUT "[rep ranking, details hidden (change flag value to view details)]\n" ;
1784             }
1785             }
1786              
1787              
1788             #-----------------------------------------------
1789             # Starting representation calculations.
1790              
1791 16 50       40 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, starting representation calculations]\n" } ;
  0         0  
1792              
1793              
1794             #-----------------------------------------------
1795             # Count the number of choices to be ranked.
1796             # Also initialize the list that keeps track of
1797             # which choices have been "representation"
1798             # ranked so far.
1799             # Assume that not all the choices are
1800             # involved (which applies to calculations
1801             # needed by VoteFair party ranking), which
1802             # means that if a choice is not being used
1803             # (overall), then it is not involved in this
1804             # ranking.
1805             # Also initialize the list that holds the
1806             # results -- to indicate which choices were
1807             # not ranked in case of an early exit.
1808              
1809 16         24 $initial_choice_count_for_rep_ranking = 0 ;
1810 16         49 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
1811             {
1812 115 100       279 if ( $global_using_choice[ $actual_choice ] == $global_true )
1813             {
1814 104         118 $global_representation_ranking_for_actual_choice[ $actual_choice ] = 0 ;
1815 104         94 $initial_choice_count_for_rep_ranking ++ ;
1816 104 50       307 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, need to rank choice " . $actual_choice . "]\n" } ;
  0         0  
1817             } else
1818             {
1819 11 50       39 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, will not be ranking choice " . $actual_choice . "]\n" } ;
  0         0  
1820             }
1821             }
1822 16 50       81 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, number of choices to rank is " . $initial_choice_count_for_rep_ranking . " (out of " . $global_full_choice_count . " choices)]\n" } ;
  0         0  
1823              
1824              
1825             #-----------------------------------------------
1826             # If there are not at least two choices,
1827             # indicate an error.
1828              
1829 16 50       43 if ( $initial_choice_count_for_rep_ranking < 2 )
1830             {
1831 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[rep ranking, ERROR: number of choices for representation ranking is less than two]\n" } ;
  0         0  
1832 0         0 return ;
1833             }
1834              
1835              
1836             #-----------------------------------------------
1837             # If there are only two choices, indicate that
1838             # the second choice (not the most popular
1839             # choice) is ranked second. However, if there
1840             # is a tie at the top level, indicate those
1841             # two choices as tied for representation
1842             # ranking.
1843              
1844 16 100       44 if ( $initial_choice_count_for_rep_ranking == 2 )
1845             {
1846 2 50       6 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, number of choices for representation ranking is two]\n" } ;
  0         0  
1847 2 50       7 if ( $global_choice_count_at_top_popularity_ranking_level == 1 )
1848             {
1849 0         0 $most_preferred_choice = $global_actual_choice_at_top_popularity_ranking_level ;
1850 0         0 $global_representation_ranking_for_actual_choice[ $most_preferred_choice ] = 1 ;
1851 0         0 $global_using_choice[ $most_preferred_choice ] = $global_false ;
1852 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, first-most-representative choice is " . $most_preferred_choice . "]\n" } ;
  0         0  
1853 0         0 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
1854             {
1855 0 0 0     0 if ( ( $global_using_choice[ $actual_choice ] == $global_true ) && ( $actual_choice != $most_preferred_choice ) )
1856             {
1857 0         0 $global_representation_ranking_for_actual_choice[ $actual_choice ] = 2 ;
1858 0         0 $global_second_most_representative_actual_choice = $actual_choice ;
1859 0         0 $global_using_choice[ $actual_choice ] = $global_false ;
1860 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, second-most-representative choice is " . $actual_choice . "]\n" } ;
  0         0  
1861 0         0 last ;
1862             }
1863             }
1864             } else
1865             {
1866 2         7 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
1867             {
1868 4 50       12 if ( $global_using_choice[ $actual_choice ] == $global_true )
1869             {
1870 4         7 $global_representation_ranking_for_actual_choice[ $actual_choice ] = 1 ;
1871 4         7 $global_using_choice[ $actual_choice ] = $global_false ;
1872 4 50       15 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, two-way tie, most representative choice is " . $actual_choice . "]\n" } ;
  0         0  
1873             }
1874             }
1875             }
1876 2 50       7 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, the only two choices have been ranked, done with representation ranking]\n" } ;
  0         0  
1877 2         5 return ;
1878             }
1879              
1880              
1881             #-----------------------------------------------
1882             # Specify how many representation levels
1883             # should be calculated.
1884             # It cannot exceed the maximum allowance.
1885             # This is used as a minimum, and is exceeded if
1886             # there are ties or if just one choice remains.
1887              
1888 14 100       44 if ( $global_representation_levels_requested > $global_limit_on_representation_rank_levels )
1889             {
1890 1         4 $global_representation_levels_requested = $global_limit_on_representation_rank_levels ;
1891             }
1892 14 50       41 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, will calculate " . $global_representation_levels_requested . " representation levels]\n" } ;
  0         0  
1893              
1894              
1895             #-----------------------------------------------
1896             # If no representation calculations should
1897             # be done, indicate that and return.
1898              
1899 14 50       46 if ( $global_representation_levels_requested < 1 )
1900             {
1901 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[rep ranking, no representation calculations were requested]\n" } ;
  0         0  
1902 0         0 return ;
1903             }
1904              
1905              
1906             #-----------------------------------------------
1907             #-----------------------------------------------
1908             # Begin the loop that identifies each pair of
1909             # most-representative choices.
1910             #
1911             # Assume that the most popular choice has
1912             # already been determined.
1913             #
1914             # The first time through this loop, most of the
1915             # first half of the loop identifies the
1916             # second-most representative choice, and
1917             # the second half of the loop identifies the
1918             # third-most representative choice (which is
1919             # the most popular choice among the remaining
1920             # choices, without any representation
1921             # adjustment.
1922             # The second time through this loop the
1923             # fourth-most representative and fifth-most
1924             # representative choices are identified.
1925             # Etc.
1926              
1927 14         17 $number_of_choices_rep_ranked = 0 ;
1928 14         15 $number_of_representation_levels_ranked = 0 ;
1929 14         21 $global_second_most_representative_actual_choice = 0 ;
1930 14         30 while ( $global_true )
1931             {
1932              
1933              
1934             #-----------------------------------------------
1935             # Count the next representation level.
1936              
1937 28         36 $number_of_representation_levels_ranked ++ ;
1938 28 50       62 if ( $global_logging_info == $global_true ) { print LOGOUT "[rep ranking, identifying choices at representation level " . $number_of_representation_levels_ranked . "]\n" } ;
  28         203  
1939              
1940              
1941             #-----------------------------------------------
1942             # Using the VoteFair popularity ranking results,
1943             # if there is just one currently most preferred
1944             # choice (among the remaining choices), identify
1945             # it as the first-most (or next-most)
1946             # representative choice.
1947              
1948 28 50       80 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, there are " . $global_choice_count_at_top_popularity_ranking_level . " choices at the most popular level]\n" } ;
  0         0  
1949 28 100       77 if ( $global_choice_count_at_top_popularity_ranking_level == 1 )
    50          
1950             {
1951 24         85 $most_preferred_choice = $global_actual_choice_at_top_popularity_ranking_level ;
1952 24         53 $global_representation_ranking_for_actual_choice[ $most_preferred_choice ] = $number_of_representation_levels_ranked ;
1953 24         30 $global_using_choice[ $most_preferred_choice ] = $global_false ;
1954 24 50       65 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, choice " . $most_preferred_choice . " is at rep level " . $number_of_representation_levels_ranked . " (at repcase 1)]\n" } ;
  0         0  
1955 24         42 $number_of_choices_rep_ranked ++ ;
1956 24         45 $previous_most_representative_choice = $most_preferred_choice ;
1957              
1958              
1959             #-----------------------------------------------
1960             # If there is a tie at this level, rank the tied
1961             # choices at the current representation ranking
1962             # level, rank the remaining choices at the next
1963             # level, indicate that a tie-breaking vote must be
1964             # introduced before the full representation
1965             # ranking can be determined, and exit the main loop.
1966              
1967             } elsif ( $global_choice_count_at_top_popularity_ranking_level > 1 )
1968             {
1969 4 50       10 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, at this representation ranking a tie -- among " . $global_choice_count_at_top_popularity_ranking_level . " choices -- has been encountered]\n" } ;
  0         0  
1970 4         13 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
1971             {
1972 19         23 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
1973 19 100       105 if ( $global_popularity_ranking_for_actual_choice[ $actual_choice ] == 1 )
1974             {
1975 9         15 $global_representation_ranking_for_actual_choice[ $actual_choice ] = $number_of_representation_levels_ranked ;
1976             } else
1977             {
1978 10         13 $global_representation_ranking_for_actual_choice[ $actual_choice ] = $number_of_representation_levels_ranked + 1 ;
1979             }
1980 19         19 $global_using_choice[ $actual_choice ] = $global_false ;
1981 19 50       54 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, choice " . $actual_choice . " is at rep level " . $global_representation_ranking_for_actual_choice[ $actual_choice ] . " (at repcase 2)]\n" } ;
  0         0  
1982             }
1983 4 50       11 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, exiting loop because of tie]\n" } ;
  0         0  
1984 4         6 last ;
1985             } else
1986             {
1987 0         0 $global_output_warning_messages_case_or_question_specific .= "case-" . $global_case_number . "-question-" . $global_question_number . "-results-type-representation-warning-message:\n" . "ERROR: zero choices popularity ranked, so program bug!" . $global_warning_end ;
1988 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[rep ranking, ERROR: zero choices popularity ranked, so program bug!]\n" } ;
  0         0  
1989 0         0 return ;
1990             }
1991              
1992              
1993             #-----------------------------------------------
1994             # If there is just one remaining choice, rank it
1995             # as least representative, and exit the loop.
1996              
1997 24 100       73 if ( $number_of_choices_rep_ranked == $initial_choice_count_for_rep_ranking - 1 )
1998             {
1999 2         11 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
2000             {
2001 8 100       21 if ( $global_using_choice[ $actual_choice ] == $global_true )
2002             {
2003 2         3 $single_nonranked_choice = $actual_choice ;
2004 2         5 last ;
2005             }
2006             }
2007 2         2 $number_of_representation_levels_ranked ++ ;
2008 2         5 $global_representation_ranking_for_actual_choice[ $single_nonranked_choice ] = $number_of_representation_levels_ranked ;
2009 2 50       7 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, choice " . $single_nonranked_choice . " is the only choice remaining]\n" } ;
  0         0  
2010 2         3 $global_using_choice[ $single_nonranked_choice ] = $global_false ;
2011 2 50       16 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, choice " . $single_nonranked_choice . " is at rep level " . $number_of_representation_levels_ranked . " (at repcase 3)]\n" } ;
  0         0  
2012 2         3 $number_of_choices_rep_ranked ++ ;
2013 2 50       7 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, exiting loop because ranked last choice]\n" } ;
  0         0  
2014 2         4 $global_using_choice[ $previous_most_representative_choice ] = $global_false ;
2015 2         3 last ;
2016             }
2017              
2018              
2019             #-----------------------------------------------
2020             # If no more representation calculations are
2021             # needed, exit the main loop.
2022              
2023 22 50       68 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, number of rep ranked choices is " . $number_of_choices_rep_ranked . "]\n" } ;
  0         0  
2024 22 50       56 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, current representation level is " . $number_of_representation_levels_ranked . " (for repcase 3)]\n" } ;
  0         0  
2025 22 50 33     115 if ( ( $number_of_choices_rep_ranked >= $initial_choice_count_for_rep_ranking ) || ( $number_of_representation_levels_ranked >= $global_representation_levels_requested ) )
2026             {
2027 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, exiting loop because no more representation ranking needed]\n" } ;
  0         0  
2028 0         0 $global_using_choice[ $previous_most_representative_choice ] = $global_false ;
2029 0         0 last ;
2030             }
2031              
2032              
2033             #-----------------------------------------------
2034             # Indicate the previously most popular choice is
2035             # no longer considered in the remaining steps.
2036              
2037 22         40 $global_using_choice[ $previous_most_representative_choice ] = $global_false ;
2038 22 50       64 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, choice " . $previous_most_representative_choice . " is ignored]\n" } ;
  0         0  
2039              
2040              
2041             #-----------------------------------------------
2042             #-----------------------------------------------
2043             # Restart at the beginning of all the ballots.
2044              
2045 22         73 &reset_ballot_info_and_tally_table( ) ;
2046              
2047              
2048             #-----------------------------------------------
2049             # Specify the normal influence of one vote per ballot.
2050              
2051 22         32 $global_ballot_influence_amount = 1.0 ;
2052              
2053              
2054             #-----------------------------------------------
2055             # Ignore any ballot in which the previous
2056             # most representative choice
2057             # (from among the non-ignored choices)
2058             # is ranked at the first preference level.
2059             #
2060             # For the remaining ballots, ignore the
2061             # previous most representative choice
2062             # and convert the remaining ballot information
2063             # into numbers in a new tally table.
2064              
2065 22 50       50 if ( $global_logging_info == $global_true ) { print LOGOUT "[rep ranking, now excluding ballots that rank choice " . $previous_most_representative_choice . " as most preferred, and excluding that choice from the available choices]\n" } ;
  22         62  
2066 22         42 $non_ignored_vote_count = 0 ;
2067 22         64 while ( $global_true )
2068             {
2069 124         228 $global_ballot_info_repeat_count = &get_numbers_based_on_one_ballot( ) ;
2070 124 100       326 if ( $global_ballot_info_repeat_count < 1 )
2071             {
2072 22         42 last ;
2073             }
2074 102 100       197 if ( $global_ballot_preference_for_choice[ $previous_most_representative_choice ] > 1 )
2075             {
2076 86         167 &add_preferences_to_tally_table( ) ;
2077 86         207 $non_ignored_vote_count += $global_ballot_info_repeat_count ;
2078             } else
2079             {
2080 16 50       38 if ( $global_logging_info == $global_true ) { print LOGOUT "[rep ranking, excluded]\n" } ;
  16         43  
2081             }
2082             }
2083              
2084              
2085             #-----------------------------------------------
2086             # Calculate the number of votes ignored and the
2087             # number of votes not ignored.
2088              
2089 22         27 $ignored_vote_count = $global_current_total_vote_count - $non_ignored_vote_count ;
2090 22 50       50 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, " . $non_ignored_vote_count . " ballots tallied, " . $ignored_vote_count . " ballots ignored]\n" } ;
  0         0  
2091              
2092              
2093             #-----------------------------------------------
2094             # If all the ballots were ignored, skip ahead to
2095             # calculate the popularity of the remaining choices.
2096              
2097 22 50       63 if ( $non_ignored_vote_count == 0 )
2098             {
2099 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, all the ballots have been ignored, so skipping several sections of code and then will calculate the popularity of the remaining choices]\n" } ;
  0         0  
2100             } else
2101             {
2102              
2103              
2104             #-----------------------------------------------
2105             # Based on the information in the tally table,
2106             # and with some choices ignored,
2107             # identify the overall popularity ranking.
2108              
2109 22 50       59 if ( $global_logging_info == $global_true ) { print LOGOUT "[rep ranking, ranking remaining choices (case 1)]\n" } ;
  22         47  
2110 22         52 &calc_votefair_popularity_rank( ) ;
2111              
2112              
2113             #-----------------------------------------------
2114             # Identify the first-most preferred choice.
2115              
2116 22 50       82 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, there are " . $global_choice_count_at_top_popularity_ranking_level . " choices at the most popular level]\n" } ;
  0         0  
2117 22 100       71 if ( $global_choice_count_at_top_popularity_ranking_level == 1 )
    50          
2118             {
2119 20         51 $alternative_most_preferred_choice = $global_actual_choice_at_top_popularity_ranking_level ;
2120 20 50       69 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, choice " . $alternative_most_preferred_choice . " is most preferred]\n" } ;
  0         0  
2121             } elsif ( $global_choice_count_at_top_popularity_ranking_level > 1 )
2122             {
2123              
2124              
2125             #-----------------------------------------------
2126             # If there is a tie at this level, indicate it
2127             # and exit the main loop.
2128              
2129 2         6 $tie_exists = $global_true ;
2130 2 50       8 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, two or more choices are tied as most-popular among the voters who did not rank the first-most representative choice at the first preference level]\n" } ;
  0         0  
2131 2         4 $number_of_representation_levels_ranked ++ ;
2132 2         8 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
2133             {
2134 15         18 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
2135 15 100       30 if ( $global_popularity_ranking_for_actual_choice[ $actual_choice ] == 1 )
2136             {
2137 5         11 $global_representation_ranking_for_actual_choice[ $actual_choice ] = $number_of_representation_levels_ranked ;
2138             } else
2139             {
2140 10         15 $global_representation_ranking_for_actual_choice[ $actual_choice ] = $number_of_representation_levels_ranked + 1 ;
2141             }
2142 15         24 $global_using_choice[ $actual_choice ] = $global_false ;
2143 15 50       47 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, choice " . $actual_choice . " is at rep level " . $global_representation_ranking_for_actual_choice[ $actual_choice ] . " (at repcase 4)]\n" } ;
  0         0  
2144             }
2145 2 50       7 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, exiting loop because of tie]\n" } ;
  0         0  
2146 2         5 $global_using_choice[ $previous_most_representative_choice ] = $global_false ;
2147 2         7 last ;
2148             } else
2149             {
2150 0         0 $global_output_warning_messages_case_or_question_specific .= "case-" . $global_case_number . "-question-" . $global_question_number . "-results-type-representation-warning-message:\n" . "ERROR: zero choices popularity ranked, so program bug!" . $global_warning_end ;
2151 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[rep ranking, ERROR: zero choices popularity ranked, so program bug!]\n" } ;
  0         0  
2152 0         0 return ;
2153             }
2154              
2155              
2156             #-----------------------------------------------
2157             # Ignore the previous most representative choice
2158             # in the remaining calculations.
2159              
2160 20         39 $global_using_choice[ $previous_most_representative_choice ] = $global_false ;
2161              
2162              
2163             #-----------------------------------------------
2164             #-----------------------------------------------
2165             # Again restart at the beginning of all the ballots.
2166              
2167 20         83 &reset_ballot_info_and_tally_table( ) ;
2168              
2169              
2170             #-----------------------------------------------
2171             # Count the number of ballots in which
2172             # the previous most representative choice is
2173             # preferred over the alternative-most-preferred choice,
2174             # which was just identified.
2175              
2176 20 50       52 if ( $global_logging_info == $global_true ) { print LOGOUT "[rep ranking, counting ballots that rank choice " . $previous_most_representative_choice . " as preferred more than choice " . $alternative_most_preferred_choice . "]\n" } ;
  20         74  
2177 20         32 $vote_count_for_reduced_influence = 0 ;
2178 20         46 while ( $global_true )
2179             {
2180 116         203 $global_ballot_info_repeat_count = &get_numbers_based_on_one_ballot( ) ;
2181 116 100       269 if ( $global_ballot_info_repeat_count < 1 )
2182             {
2183 20         26 last ;
2184             }
2185 96 100       220 if ( $global_ballot_preference_for_choice[ $previous_most_representative_choice ] <= $global_ballot_preference_for_choice[ $alternative_most_preferred_choice ] )
2186             {
2187 70         72 $vote_count_for_reduced_influence += $global_ballot_info_repeat_count ;
2188 70 50       133 if ( $global_logging_info == $global_true ) { print LOGOUT "[rep ranking, counted]\n" } ;
  70         175  
2189             }
2190             }
2191 20 50       53 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, vote count for reduced influence is " . $vote_count_for_reduced_influence . "]\n" } ;
  0         0  
2192              
2193              
2194             #-----------------------------------------------
2195             # Calculate the reduced influence that is appropriate
2196             # for voters who are already well-represented by the
2197             # first-most representative choice.
2198              
2199 20 50       42 if ( $vote_count_for_reduced_influence >= 1 )
2200             {
2201 20         45 $reduced_influence_amount = ( $vote_count_for_reduced_influence - ( $global_current_total_vote_count / 2.0 ) ) / $vote_count_for_reduced_influence ;
2202 20 50       49 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, influence reduced by: " . $reduced_influence_amount . "]\n" } ;
  0         0  
2203             } else
2204             {
2205 0         0 $reduced_influence_amount = 0 ;
2206 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, no ballots need their influence reduced]\n" } ;
  0         0  
2207             }
2208 20 50       69 if ( $reduced_influence_amount < 0 )
2209             {
2210 0         0 $reduced_influence_amount = 0 ;
2211 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, the number calculated for the amount of reduced influence is less than zero, so a zero value is used instead]\n" } ;
  0         0  
2212             }
2213              
2214              
2215             #-----------------------------------------------
2216             #-----------------------------------------------
2217             # Again restart at the beginning of all the ballots.
2218              
2219 20         40 &reset_ballot_info_and_tally_table( ) ;
2220              
2221              
2222             #-----------------------------------------------
2223             # Again convert the ballot information into
2224             # numbers in a new tally table. Reduce the
2225             # influence of any ballot in which the previous
2226             # most representative choice is preferred over
2227             # the alternative-most-preferred choice.
2228             # For other ballots, use the normal amount of
2229             # influence. However, scale the decimal
2230             # values to integer numbers -- so that tied
2231             # situations are correctly handled.
2232              
2233 20 50       102 if ( $global_logging_info == $global_true ) { print LOGOUT "[rep ranking, calculating popularity ranking with reduced influence -- of " . sprintf( "%0.4f" , $reduced_influence_amount ) . " -- for the " . $vote_count_for_reduced_influence . " ballots that prefer choice " . $previous_most_representative_choice . " more than choice " . $alternative_most_preferred_choice . ", and scaling decimal pairwise counts by " . ( $vote_count_for_reduced_influence * 10 ) . "]\n" } ;
  20         230  
2234 20         65 while ( $global_true )
2235             {
2236 116         212 $global_ballot_info_repeat_count = &get_numbers_based_on_one_ballot( ) ;
2237 116 100       273 if ( $global_ballot_info_repeat_count < 1 )
2238             {
2239 20         40 last ;
2240             }
2241 96 100       207 if ( $global_ballot_preference_for_choice[ $previous_most_representative_choice ] <= $global_ballot_preference_for_choice[ $alternative_most_preferred_choice ] )
2242             {
2243 70         111 $global_ballot_influence_amount = int( $reduced_influence_amount * $vote_count_for_reduced_influence * 10 ) ;
2244 70 50       141 if ( $global_logging_info == $global_true ) { print LOGOUT "[rep ranking, reduced]\n" } ;
  70         108  
2245             } else
2246             {
2247 26         48 $global_ballot_influence_amount = int( 1.0 * $vote_count_for_reduced_influence * 10 );
2248             }
2249 96         167 &add_preferences_to_tally_table ;
2250             }
2251              
2252              
2253             #-----------------------------------------------
2254             # Based on the information in the tally table,
2255             # identify the overall popularity ranking.
2256              
2257 20 50       58 if ( $global_logging_info == $global_true ) { print LOGOUT "[rep ranking, ranking remaining choices (case 2)]\n" } ;
  20         34  
2258 20         56 &calc_votefair_popularity_rank( ) ;
2259              
2260              
2261             #-----------------------------------------------
2262             # Count the next representation level.
2263              
2264 20         43 $number_of_representation_levels_ranked ++ ;
2265 20 50       76 if ( $global_logging_info == $global_true ) { print LOGOUT "[rep ranking, identifying choices at representation ranking " . $number_of_representation_levels_ranked . "]\n" } ;
  20         63  
2266              
2267              
2268             #-----------------------------------------------
2269             # If there is just one currently most preferred
2270             # choice, identify it as the next-most representative
2271             # choice based on the reduced influence of the
2272             # identified ballots.
2273              
2274 20 100       51 if ( $global_choice_count_at_top_popularity_ranking_level == 1 )
2275             {
2276 19         34 $most_preferred_choice = $global_actual_choice_at_top_popularity_ranking_level ;
2277 19 50       56 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, choice " . $most_preferred_choice . " is most preferred]\n" } ;
  0         0  
2278 19         42 $global_representation_ranking_for_actual_choice[ $most_preferred_choice ] = $number_of_representation_levels_ranked ;
2279 19         42 $global_using_choice[ $most_preferred_choice ] = $global_false ;
2280 19 50       54 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, choice " . $most_preferred_choice . " is at rep level " . $number_of_representation_levels_ranked . " (at repcase 6)]\n" } ;
  0         0  
2281 19         32 $number_of_choices_rep_ranked ++ ;
2282 19         52 $previous_most_representative_choice = $most_preferred_choice ;
2283              
2284              
2285             #-----------------------------------------------
2286             # If there is a tie at this level, list the tied
2287             # choices, indicate that a tie-breaking vote must be
2288             # introduced before the next-most representative
2289             # choices can be identified, and exit the main loop.
2290              
2291             } else
2292             {
2293 1 50       6 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, at this representation ranking -- after reducing the influence of well-represented voters -- a tie has been encountered. A tie-breaking vote is needed to go further]\n" } ;
  0         0  
2294 1         6 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
2295             {
2296 5         6 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
2297 5 100       9 if ( $global_popularity_ranking_for_actual_choice[ $actual_choice ] == 1 )
2298             {
2299 2         5 $global_representation_ranking_for_actual_choice[ $actual_choice ] = $number_of_representation_levels_ranked ;
2300             } else
2301             {
2302 3         5 $global_representation_ranking_for_actual_choice[ $actual_choice ] = $number_of_representation_levels_ranked + 1 ;
2303             }
2304 5         6 $global_using_choice[ $actual_choice ] = $global_false ;
2305 5 50       17 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, choice " . $actual_choice . " is at rep level " . $global_representation_ranking_for_actual_choice[ $actual_choice ] . " (at repcase 7)]\n" } ;
  0         0  
2306             }
2307 1 50       5 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, exiting loop because of tie]\n" } ;
  0         0  
2308 1         4 last ;
2309             }
2310              
2311              
2312             #-----------------------------------------------
2313             # This is where the code skips ahead to if all
2314             # the voters indicate the previous-most
2315             # representative choice as their first choice.
2316              
2317             }
2318              
2319              
2320             #-----------------------------------------------
2321             #-----------------------------------------------
2322             # If there is just one remaining choice, rank it
2323             # as least representative, and exit the loop.
2324              
2325 19 100       71 if ( $initial_choice_count_for_rep_ranking - $number_of_choices_rep_ranked == 1 )
2326             {
2327 1         5 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
2328             {
2329 1 50       4 if ( $global_using_choice[ $actual_choice ] == $global_true )
2330             {
2331 1         1 $single_nonranked_choice = $actual_choice ;
2332 1         2 last ;
2333             }
2334             }
2335 1         2 $number_of_representation_levels_ranked ++ ;
2336 1 50       3 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, choice " . $single_nonranked_choice . " is the only choice remaining]\n" } ;
  0         0  
2337 1         2 $global_representation_ranking_for_actual_choice[ $single_nonranked_choice ] = $number_of_representation_levels_ranked ;
2338 1         2 $global_using_choice[ $single_nonranked_choice ] = $global_false ;
2339 1 50       11 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, choice " . $single_nonranked_choice . " is at rep level " . $number_of_representation_levels_ranked . " (at repcase 8)]\n" } ;
  0         0  
2340 1         1 $number_of_choices_rep_ranked ++ ;
2341 1 50       3 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, exiting loop because ranked last choice]\n" } ;
  0         0  
2342 1         3 last ;
2343             }
2344              
2345              
2346             #-----------------------------------------------
2347             # If no more representation calculations are
2348             # needed, exit the main loop.
2349              
2350 18 50       49 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, number of rep ranked choices is " . $number_of_choices_rep_ranked . "]\n" } ;
  0         0  
2351 18 50       48 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, next representation level is " . $number_of_representation_levels_ranked . " (for repcase 8)]\n" } ;
  0         0  
2352 18 100 66     122 if ( ( $number_of_choices_rep_ranked >= $initial_choice_count_for_rep_ranking ) || ( $number_of_representation_levels_ranked >= $global_representation_levels_requested ) )
2353             {
2354 4 50       19 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, exiting loop because no more representation ranking needed]\n" } ;
  0         0  
2355 4         13 last ;
2356             }
2357              
2358              
2359             #-----------------------------------------------
2360             #-----------------------------------------------
2361             # Restart at the beginning of the ballots, and
2362             # initialize the tally table.
2363              
2364 14         59 &reset_ballot_info_and_tally_table( ) ;
2365              
2366              
2367             #-----------------------------------------------
2368             # Specify the normal influence of one vote per ballot.
2369              
2370 14         25 $global_ballot_influence_amount = 1.0 ;
2371              
2372              
2373             #-----------------------------------------------
2374             # Convert the ballot information -- for the
2375             # remaining choices -- into preferences in a
2376             # new tally table.
2377              
2378 14 50       53 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[rep ranking, calculating popularity ranking for remaining choices]\n" } ;
  0         0  
2379 14         37 while ( $global_true )
2380             {
2381 82         153 $global_ballot_info_repeat_count = &get_numbers_based_on_one_ballot( ) ;
2382 82 100       202 if ( $global_ballot_info_repeat_count < 1 )
2383             {
2384 14         21 last ;
2385             }
2386 68         132 &add_preferences_to_tally_table ;
2387             }
2388              
2389              
2390             #-----------------------------------------------
2391             # Based on the information in the tally table,
2392             # identify the overall popularity ranking.
2393              
2394 14 50       43 if ( $global_logging_info == $global_true ) { print LOGOUT "[rep ranking, ranking remaining choices (case 3)]\n" } ;
  14         30  
2395 14         42 &calc_votefair_popularity_rank( ) ;
2396              
2397              
2398             #-----------------------------------------------
2399             #-----------------------------------------------
2400             # Repeat the loop that identifies each pair of
2401             # most-representative choices.
2402              
2403             }
2404              
2405              
2406             #-----------------------------------------------
2407             #-----------------------------------------------
2408             # End of subroutine.
2409              
2410 14 50       46 if ( $global_logging_info == $global_true ) { print LOGOUT "[rep ranking, done doing representation calculations]\n\n" } ;
  14         30  
2411 14 50       37 if ( $global_logging_info == $global_true ) { print LOGOUT "[rep ranking, exiting calc_votefair_representation_rank subroutine]\n\n" } ;
  14         26  
2412 14         27 return 1 ;
2413              
2414             }
2415              
2416              
2417              
2418              
2419             =head2 calc_votefair_party_rank
2420              
2421             (Not exported, for internal use only.)
2422              
2423             Calculates VoteFair party ranking results, as
2424             described in the book "Ending The Hidden
2425             Unfairness In U.S. Elections."
2426             These results are used to determine the
2427             maximum number of candidates each
2428             political party is allowed to offer
2429             in one election. The number of allowed
2430             candidates will vary according to the
2431             election type, with less-important elections
2432             not having any limits, and very important
2433             elections, such as for U.S. President, allowing
2434             two candidates each from the first-ranked and
2435             second-ranked parties, one candidate each from
2436             the next three or four parties, and no
2437             candidates from any other parties.
2438              
2439             =cut
2440              
2441             #-----------------------------------------------
2442             #-----------------------------------------------
2443             # calc_votefair_party_rank
2444             #-----------------------------------------------
2445             #-----------------------------------------------
2446              
2447             sub calc_votefair_party_rank
2448             {
2449              
2450 10     10 1 20 my $actual_choice ;
2451             my $adjusted_choice ;
2452 0         0 my $first_party_choice ;
2453 0         0 my $second_party_choice ;
2454 0         0 my $third_party_choice ;
2455 0         0 my $next_party_choice ;
2456 0         0 my $party_ranking_level ;
2457 0         0 my $count_of_parties_ranked ;
2458 0         0 my $non_ignored_vote_count ;
2459 0         0 my $choice_specific_ranking_level ;
2460              
2461              
2462             #-----------------------------------------------
2463             # Also do other initialization.
2464              
2465 10 50       44 if ( $global_logging_info == $global_true ) { print LOGOUT "\n[party ranking, beginning VoteFair party ranking calculations]\n" } ;
  10         16  
2466 10         23 $global_ballot_influence_amount = 1.0 ;
2467 10         17 $count_of_parties_ranked = 0 ;
2468 10         24 $first_party_choice = 0 ;
2469 10         47 $second_party_choice = 0 ;
2470 10         16 $third_party_choice = 0 ;
2471 10         15 $party_ranking_level = 1 ;
2472              
2473              
2474             #-----------------------------------------------
2475             # If there are no choices, return.
2476              
2477 10 50       32 if ( $global_full_choice_count < 1 )
2478             {
2479 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, Warning, no choices to rank for VoteFair party ranking]\n" } ;
  0         0  
2480 0         0 return ;
2481             }
2482              
2483              
2484             #-----------------------------------------------
2485             # Initialize the party ranking results to all
2486             # be unranked.
2487              
2488 10         30 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
2489             {
2490 75         146 $global_party_ranking_for_actual_choice[ $actual_choice ] = 0 ;
2491             }
2492              
2493              
2494             #-----------------------------------------------
2495             # If there is only one choice, indicate that
2496             # the party is ranked in first place, and
2497             # then return.
2498              
2499 10 50       27 if ( $global_full_choice_count == 1 )
2500             {
2501 0         0 $global_party_ranking_for_actual_choice[ 1 ] = 1 ;
2502 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, only one choice to rank, so done with party ranking]\n" } ;
  0         0  
2503 0         0 return ;
2504             }
2505              
2506              
2507             #-----------------------------------------------
2508             # Identify the first-ranked political party
2509             # as the most-popular party according to
2510             # VoteFair popularity ranking.
2511             # Instead of re-calculating, use the results
2512             # that were saved before VoteFair representation
2513             # ranking results were calculated.
2514              
2515 10 100       27 if ( $global_choice_count_at_full_top_popularity_ranking_level == 1 )
    100          
2516             {
2517 8         11 $party_ranking_level = 1 ;
2518 8         13 $first_party_choice = $global_actual_choice_at_top_of_full_popularity_ranking ;
2519 8         15 $global_party_ranking_for_actual_choice[ $first_party_choice ] = $party_ranking_level ;
2520 8 50       19 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, most preferred, is choice " . $first_party_choice . "]\n" } ;
  8         22  
2521 8         16 $count_of_parties_ranked = 1 ;
2522 8         9 $party_ranking_level ++ ;
2523              
2524              
2525             #-----------------------------------------------
2526             # If there is a two-way tie at this first level,
2527             # use these two choices as the top two political
2528             # parties (with neither being identified as more
2529             # popular than the other). In this case the
2530             # next party ranking level will be 3.
2531              
2532             } elsif ( $global_choice_count_at_full_top_popularity_ranking_level == 2 )
2533             {
2534 1         4 $party_ranking_level = 1 ;
2535 1 50       4 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, there is a two-way tie for first choice, so a tie-breaking ballot must be added]\n" } ;
  1         2  
2536 1         4 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
2537             {
2538 3 100       9 if ( $global_full_popularity_ranking_for_actual_choice[ $actual_choice ] == 1 )
2539             {
2540 2 100       6 if ( $first_party_choice == 0 )
    50          
2541             {
2542 1         3 $first_party_choice = $actual_choice ;
2543 1         3 $global_party_ranking_for_actual_choice[ $first_party_choice ] = $party_ranking_level ;
2544             } elsif ( $second_party_choice == 0 )
2545             {
2546 1         2 $second_party_choice = $actual_choice ;
2547 1         1 $global_party_ranking_for_actual_choice[ $second_party_choice ] = $party_ranking_level ;
2548 1         3 last ;
2549             }
2550             }
2551             }
2552 1 50       2 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, tie at top between " . $first_party_choice . " and " . $second_party_choice . "]\n" } ;
  1         4  
2553 1         2 $count_of_parties_ranked = 2 ;
2554 1         1 $party_ranking_level = 3 ;
2555              
2556              
2557             #-----------------------------------------------
2558             # If there is any other kind of tie at this
2559             # first level, indicate that a tie-breaking
2560             # vote must be introduced before the
2561             # next-ranked party can be identified, rank
2562             # the tied choices at level one, rank the
2563             # remaining choices at level three, and
2564             # exit this subroutine.
2565              
2566             } else
2567             {
2568 1         2 $party_ranking_level = 1 ;
2569 1 50       3 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, there is a tie for first choice, so a tie-breaking ballot must be added]\n" } ;
  1         2  
2570 1         3 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
2571             {
2572 3 50       7 if ( $global_full_popularity_ranking_for_actual_choice[ $actual_choice ] == 1 )
    0          
2573             {
2574 3         4 $global_party_ranking_for_actual_choice[ $actual_choice ] = $party_ranking_level ;
2575 3 50       7 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, tied choice: " . $actual_choice . "]\n" } ;
  3         26  
2576             } elsif ( $global_party_ranking_for_actual_choice[ $actual_choice ] == 0 )
2577             {
2578 0         0 $global_party_ranking_for_actual_choice[ $actual_choice ] = 3 ;
2579 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, at (bottom) level 3 is choice " . $actual_choice . "]\n" } ;
  0         0  
2580             }
2581             }
2582 1         3 $global_output_warning_messages_case_or_question_specific .= $global_question_specific_warning_begin . " first-place-tie-in-VoteFair-party-ranking-so-tie-breaking-vote-needed" . "\n-----\n\n" ;
2583 1 50       4 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, exit multi_pop_tie, done with party ranking]\n" } ;
  1         1  
2584 1         4 return ;
2585             }
2586              
2587              
2588             #-----------------------------------------------
2589             # Specify that the second-ranked party is the
2590             # same as the second-ranked choice according to
2591             # VoteFair representation ranking (which has
2592             # already been calculated).
2593              
2594 9 100       31 if ( $count_of_parties_ranked == 1 )
2595             {
2596 8 100       33 if ( $global_choice_count_at_full_second_representation_level == 1 )
2597             {
2598 6         10 $party_ranking_level = 2 ;
2599 6         7 $second_party_choice = $global_actual_choice_at_second_representation_ranking ;
2600 6         9 $global_party_ranking_for_actual_choice[ $second_party_choice ] = 2 ;
2601 6 50       19 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, second-most preferred, is choice " . $second_party_choice . "]\n" } ;
  6         12  
2602 6         9 $count_of_parties_ranked ++ ;
2603 6         11 $party_ranking_level ++ ;
2604              
2605              
2606             #-----------------------------------------------
2607             # If the VoteFair representation ranking
2608             # results had a tie in the
2609             # second-most-representative position,
2610             # indicate that a tie-breaking vote must be
2611             # introduced before the next-ranked party
2612             # can be identified, rank the tied choices at
2613             # level two, rank the remaining choices at
2614             # level three, and then exit this subroutine.
2615              
2616             } else
2617             {
2618 2         3 $party_ranking_level = 2 ;
2619 2 50       7 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, there is a tie for second choice, so a tie-breaking ballot must be added]\n" } ;
  2         4  
2620 2         7 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
2621             {
2622 18 50       37 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, representation rank for choice " . $actual_choice . " is " . $global_full_representation_ranking_for_actual_choice[ $actual_choice ] . "]\n" } ;
  18         52  
2623 18 100       47 if ( $global_full_representation_ranking_for_actual_choice[ $actual_choice ] == 2 )
    100          
2624             {
2625 5         9 $global_party_ranking_for_actual_choice[ $actual_choice ] = $party_ranking_level ;
2626 5         6 $count_of_parties_ranked ++ ;
2627 5 50       20 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, tied choice: " . $actual_choice . "]\n" } ;
  5         18  
2628             } elsif ( $global_party_ranking_for_actual_choice[ $actual_choice ] == 0 )
2629             {
2630 11         19 $global_party_ranking_for_actual_choice[ $actual_choice ] = $party_ranking_level + 1 ;
2631 11 50       20 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, at bottom level " . $party_ranking_level . ", is choice " . $actual_choice . "]\n" } ;
  11         41  
2632             }
2633             }
2634 2 50       13 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, exit rep_tie, done with party ranking]\n" } ;
  2         5  
2635 2         5 return ;
2636             }
2637             }
2638              
2639              
2640             #-----------------------------------------------
2641             # If there are only two choices (total),
2642             # return.
2643              
2644 7 50       25 if ( $global_full_choice_count == 2 )
    50          
2645             {
2646 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, only two choices, so done]\n" } ;
  0         0  
2647 0         0 return ;
2648              
2649              
2650             #-----------------------------------------------
2651             # If there are only three choices, rank the
2652             # remaining party at the next ranking level.
2653              
2654             } elsif ( $global_full_choice_count == 3 )
2655             {
2656 0         0 $party_ranking_level = 3 ;
2657 0         0 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
2658             {
2659 0 0       0 if ( $global_party_ranking_for_actual_choice[ $actual_choice ] == 0 )
2660             {
2661 0         0 $global_party_ranking_for_actual_choice[ $actual_choice ] = $party_ranking_level ;
2662 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, party at third (and bottom) level is " . $actual_choice . "]\n" } ;
  0         0  
2663 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, only three choices, so done with party ranking]\n" } ;
  0         0  
2664 0         0 return ;
2665             }
2666             }
2667             }
2668              
2669              
2670             #-----------------------------------------------
2671             # Update which choices have not yet been party
2672             # ranked.
2673              
2674 7         19 &set_all_choices_as_used( ) ;
2675 7         22 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
2676             {
2677 54 100       131 if ( $global_party_ranking_for_actual_choice[ $actual_choice ] > 0 )
2678             {
2679 14         21 $global_using_choice[ $actual_choice ] = $global_false ;
2680 14 50       30 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, ignoring choice " . $actual_choice . "]" } ;
  14         46  
2681             }
2682             }
2683              
2684              
2685             #-----------------------------------------------
2686             # For the third ranking, re-count the ballots
2687             # but ignore the ballots in which the first
2688             # choice -- even if tied (ranked at the same
2689             # level as another choice) -- is the
2690             # first-ranked or second-ranked party.
2691              
2692 7 50       21 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, now excluding ballots that rank choice " . $first_party_choice . " or " . $second_party_choice . " as most preferred, even if there is a tie on the ballot]\n" } ;
  7         18  
2693 7         21 &reset_ballot_info_and_tally_table( ) ;
2694 7 50       22 if ( $global_logging_info == $global_true ) { print LOGOUT "\n" } ;
  7         18  
2695 7         8 $non_ignored_vote_count = 0 ;
2696 7         18 while ( $global_true )
2697             {
2698 46         90 $global_ballot_info_repeat_count = &get_numbers_based_on_one_ballot( ) ;
2699 46 100       95 if ( $global_ballot_info_repeat_count < 1 )
2700             {
2701 7         10 last ;
2702             } else
2703             {
2704 39 100 100     142 if ( ( $global_ballot_preference_for_choice[ $first_party_choice ] > 1 ) && ( $global_ballot_preference_for_choice[ $second_party_choice ] > 1 ) )
2705             {
2706 22         41 &add_preferences_to_tally_table( ) ;
2707 22         25 $non_ignored_vote_count += $global_ballot_info_repeat_count ;
2708 22 50       41 if ( $global_logging_info == $global_true ) { print LOGOUT "\n" } ;
  22         56  
2709             } else
2710             {
2711 17 50       39 if ( $global_logging_info == $global_true ) { print LOGOUT "[ignored]\n" } ;
  17         46  
2712             }
2713             }
2714             }
2715              
2716              
2717             #-----------------------------------------------
2718             # If at least one ballot meets this criteria,
2719             # identify the most popular party according to
2720             # the just-counted ballots (for the remaining
2721             # choices), and use that most-popular choice as
2722             # the third-ranked political party.
2723              
2724 7 100       14 if ( $non_ignored_vote_count >= 1 )
2725             {
2726 6         8 $global_ranking_type_being_calculated = "party" ;
2727 6 50       15 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, doing VoteFair popularity ranking as part of party ranking, but only with " . $non_ignored_vote_count . " ballots meeting criteria]\n" } ;
  6         18  
2728 6         14 &calc_votefair_popularity_rank( ) ;
2729 6 50       16 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, ranking choices based on ballots meeting criteria]\n" } ;
  6         13  
2730 6 100       18 if ( $global_choice_count_at_top_popularity_ranking_level == 1 )
2731             {
2732 4         8 $third_party_choice = $global_actual_choice_at_top_popularity_ranking_level ;
2733 4         7 $global_party_ranking_for_actual_choice[ $third_party_choice ] = $party_ranking_level ;
2734 4 50       17 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, third-most preferred, is choice " . $third_party_choice . "]\n" } ;
  4         19  
2735 4         8 $count_of_parties_ranked ++ ;
2736 4         8 $party_ranking_level ++ ;
2737              
2738              
2739             #-----------------------------------------------
2740             # If there is a tie -- based on using just the
2741             # ballots that meet the indicated criteria --
2742             # then indicate a tie among those parties,
2743             # then rank the remaining parties at the next
2744             # level, and then exit the subroutine.
2745              
2746             } else
2747             {
2748 2 50       7 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, there is a tie for third choice, so a tie-breaking ballot must be added]\n" } ;
  2         4  
2749 2         9 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
2750             {
2751 10         12 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
2752 10 100       28 if ( $global_popularity_ranking_for_actual_choice[ $actual_choice ] == 1 )
    50          
2753             {
2754 5         8 $global_party_ranking_for_actual_choice[ $actual_choice ] = $party_ranking_level ;
2755 5         6 $count_of_parties_ranked ++ ;
2756 5 50       10 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, tied choice: " . $actual_choice . "]\n" } ;
  5         16  
2757             } elsif ( $global_party_ranking_for_actual_choice[ $actual_choice ] == 0 )
2758             {
2759 5         8 $global_party_ranking_for_actual_choice[ $actual_choice ] = $party_ranking_level + 1 ;
2760 5 50       13 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, at bottom level " . $party_ranking_level . ", is choice " . $actual_choice . "]\n" } ;
  5         18  
2761             }
2762             }
2763 2 50       6 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, exit some_ballots_tie, done with party ranking]\n" } ;
  2         4  
2764 2         6 return ;
2765             }
2766             } else
2767             {
2768 1 50       6 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, zero ballots meet criteria]\n" } ;
  1         4  
2769             }
2770              
2771              
2772             #-----------------------------------------------
2773             # If there are no choices remaining, exit the
2774             # subroutine.
2775              
2776 5 50       31 if ( $global_full_choice_count - $count_of_parties_ranked == 0 )
    100          
2777             {
2778 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, all choices ranked, so done with party ranking]\n" } ;
  0         0  
2779 0         0 return ;
2780              
2781              
2782             #-----------------------------------------------
2783             # If there is only one choice remaining, rank
2784             # it at the bottom, and exit the subroutine.
2785              
2786             } elsif ( $global_full_choice_count - $count_of_parties_ranked == 1 )
2787             {
2788 1         5 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
2789             {
2790 1 50       3 if ( $global_party_ranking_for_actual_choice[ $actual_choice ] == 0 )
2791             {
2792 1         1 $global_party_ranking_for_actual_choice[ $actual_choice ] = $party_ranking_level ;
2793 1 50       4 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, final party choice is " . $actual_choice . "]\n" } ;
  1         3  
2794 1 50       3 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, no more choices, so done with party ranking]\n" } ;
  1         2  
2795 1         3 return ;
2796             }
2797             }
2798             }
2799              
2800              
2801             #-----------------------------------------------
2802             # Update which choices have not yet been party
2803             # ranked.
2804              
2805 4         16 &set_all_choices_as_used( ) ;
2806 4         15 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
2807             {
2808 36 100       92 if ( $global_party_ranking_for_actual_choice[ $actual_choice ] > 0 )
2809             {
2810 11         12 $global_using_choice[ $actual_choice ] = $global_false ;
2811 11 50       21 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, ignoring choice " . $actual_choice . "]\n" } ;
  11         34  
2812             }
2813             }
2814              
2815              
2816             #-----------------------------------------------
2817             # Specify the fourth (or possibly third)
2818             # ranking to be the first choice -- among the
2819             # remaining choices, using all the ballots --
2820             # according to VoteFair popularity ranking.
2821              
2822 4         14 &reset_ballot_info_and_tally_table( ) ;
2823 4 50       16 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, now considering all ballots]\n" } ;
  4         11  
2824 4         12 while ( $global_true )
2825             {
2826 24         38 $global_ballot_info_repeat_count = &get_numbers_based_on_one_ballot( ) ;
2827 24 100       43 if ( $global_ballot_info_repeat_count < 1 )
2828             {
2829 4         7 last ;
2830             } else
2831             {
2832 20         40 &add_preferences_to_tally_table( ) ;
2833             }
2834             }
2835 4 50       10 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, using popularity ranking to identify next party choice]\n" } ;
  4         9  
2836 4         12 &calc_votefair_popularity_rank( ) ;
2837 4 50       15 if ( $global_choice_count_at_top_popularity_ranking_level == 1 )
2838             {
2839 4         8 $next_party_choice = $global_actual_choice_at_top_popularity_ranking_level ;
2840 4         8 $global_party_ranking_for_actual_choice[ $next_party_choice ] = $party_ranking_level ;
2841 4 50       14 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, next most preferred, is choice " . $next_party_choice . "]\n" } ;
  4         11  
2842 4         6 $count_of_parties_ranked ++ ;
2843 4         19 $party_ranking_level ++ ;
2844              
2845              
2846             #-----------------------------------------------
2847             # If there was a tie, indicate which parties
2848             # (choices) are tied at this level, and rank
2849             # the remaining parties at the bottom, then
2850             # exit the subroutine.
2851              
2852             } else
2853             {
2854 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, there is a tie for first choice, so a tie-breaking ballot must be added]\n" } ;
  0         0  
2855 0         0 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
2856             {
2857 0         0 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
2858 0 0       0 if ( $global_popularity_ranking_for_actual_choice[ $actual_choice ] == 1 )
    0          
2859             {
2860 0         0 $global_party_ranking_for_actual_choice[ $actual_choice ] = $party_ranking_level ;
2861 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, tied choice: " . $actual_choice . "]\n" } ;
  0         0  
2862             } elsif ( $global_party_ranking_for_actual_choice[ $actual_choice ] == 0 )
2863             {
2864 0         0 $global_party_ranking_for_actual_choice[ $actual_choice ] = $party_ranking_level + 1 ;
2865 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, at bottom level " . $party_ranking_level . ", is choice " . $actual_choice . "]\n" } ;
  0         0  
2866             }
2867             }
2868 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, exit post_rep_pop_tie, done with party ranking]\n" } ;
  0         0  
2869 0         0 return ;
2870             }
2871              
2872              
2873             #-----------------------------------------------
2874             # If there is only one choice remaining,
2875             # identify it as the final choice, and then
2876             # exit the subroutine.
2877              
2878 4 50       17 if ( $global_full_choice_count - $count_of_parties_ranked == 1 )
2879             {
2880 0         0 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
2881             {
2882 0 0       0 if ( $global_party_ranking_for_actual_choice[ $actual_choice ] == 0 )
2883             {
2884 0         0 $global_party_ranking_for_actual_choice[ $actual_choice ] = $party_ranking_level ;
2885 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, final party choice is " . $actual_choice . "]\n" } ;
  0         0  
2886 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, exit post_rep_pop_last, no more choices, so done]\n" } ;
  0         0  
2887 0         0 return ;
2888             }
2889             }
2890             }
2891              
2892              
2893             #-----------------------------------------------
2894             # Use VoteFair representation ranking to
2895             # rank the remaining parties.
2896              
2897 4         9 $global_ranking_type_being_calculated = "party-representation" ;
2898 4 50       15 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, transition from party ranking to representation ranking calculations]\n" } ;
  4         12  
2899 4         8 $global_representation_levels_requested = $global_full_choice_count - $count_of_parties_ranked ;
2900 4         16 &calc_votefair_representation_rank( ) ;
2901 4 50       14 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, transition back to party ranking from representation ranking calculations]\n" } ;
  4         8  
2902 4 50       11 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, current ranking level is " . $party_ranking_level . "]\n" } ;
  4         14  
2903 4         11 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
2904             {
2905 36 100       85 if ( $global_party_ranking_for_actual_choice[ $actual_choice ] == 0 )
2906             {
2907 21 50       36 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, choice " . $actual_choice . " is at rep-rank level " . $global_representation_ranking_for_actual_choice[ $actual_choice ] . "]\n" } ;
  21         46  
2908 21         28 $choice_specific_ranking_level = $party_ranking_level - 2 + $global_representation_ranking_for_actual_choice[ $actual_choice ] ;
2909 21         28 $global_party_ranking_for_actual_choice[ $actual_choice ] = $choice_specific_ranking_level ;
2910 21 50       36 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, at party-ranked level " . $choice_specific_ranking_level . " is choice " . $actual_choice . "]\n" } ;
  21         107  
2911             }
2912             }
2913              
2914              
2915             #-----------------------------------------------
2916             # End of subroutine.
2917              
2918 4 50       12 if ( $global_logging_info == $global_true ) { print LOGOUT "[party ranking, done with party ranking]\n" } ;
  4         18  
2919 4         13 return ;
2920              
2921             }
2922              
2923              
2924              
2925              
2926             =head2 calc_votefair_choice_specific_pairwise_score_popularity_rank
2927              
2928             (Not exported, for internal use only.)
2929              
2930             Calculates VoteFair choice-specific pairwise-score
2931             (CSPS) popularity ranking results.
2932              
2933             This kind of ranking is useful for estimating
2934             the overall ranking when there are many choices
2935             (such as hundreds of choices) and fast results
2936             are desired. It is also used to estimate the
2937             ranking before doing the VoteFair
2938             insertion-sort popularity ranking calculations.
2939             (If access to a computer is not available, this
2940             CSPS method can be done using pen and paper and
2941             a calculator.)
2942              
2943             Example:
2944              
2945             (A concise description follows this
2946             example. The description is easier to
2947             understand after you have read this example.)
2948              
2949             Consider an election (or survey) in which
2950             there are five choices: A, B, C, D, E, and the
2951             final ranking order is this alphabetical
2952             order.
2953              
2954             In this example the notation A>B
2955             refers to how many voters pairwise prefer
2956             choice A over choice B, and the notation
2957             B>A refers to how many voters pairwise
2958             prefer choice B over choice A. This
2959             notation always uses the "greater-than" symbol
2960             ">", and never uses the "less-than" symbol
2961             "<".
2962              
2963             At the beginning of this ranking example,
2964             suppose that the choices are arranged in the
2965             order C, E, A, D, B. The pairwise counts
2966             for this arrangement are shown in this pairwise
2967             matrix.
2968              
2969             | | | | | |
2970             | C | E | A | D | B |
2971             | | | | | |
2972             -----+-------+-------+-------+-------+-------+
2973             | \ | | | | |
2974             C | \ | C>E | C>A | C>D | C>B |
2975             | \ | | | | |
2976             -----+-------+-------+-------+-------+-------+
2977             | | \ | | | |
2978             E | E>C | \ | E>A | E>D | E>B |
2979             | | \ | | | |
2980             -----+-------+-------+-------+-------+-------+
2981             | | | \ | | |
2982             A | A>C | A>E | \ | A>D | A>B |
2983             | | | \ | | |
2984             -----+-------+-------+-------+-------+-------+
2985             | | | | \ | |
2986             D | D>C | D>E | D>A | \ | D>B |
2987             | | | | \ | |
2988             -----+-------+-------+-------+-------+-------+
2989             | | | | | \ |
2990             B | B>C | B>E | B>A | B>D | \ |
2991             | | | | | \ |
2992             -----+-------+-------+-------+-------+-------+
2993              
2994             The diagonal line passes through empty
2995             cells. These cells are empty because they
2996             would represent a choice's comparison with
2997             itself, such as A>A.
2998              
2999             The goal of these calculations is to change
3000             the sequence so that the largest pairwise
3001             counts move into the upper-right triangular
3002             area, leaving the smallest pairwise counts in
3003             the lower-left triangular area. (This is
3004             similar to the goal of VoteFair popularity
3005             ranking.)
3006              
3007             The first step is to calculate
3008             choice-specific scores, with each choice having
3009             a row score and a column
3010             score. For choice A, its row score
3011             equals the sum of the pairwise counts in the
3012             row labelled A, which equals A>B +
3013             A>C + A>D + A>E. The column
3014             score for choice A is the sum of the
3015             pairwise counts in the column labeled A,
3016             which equals B>A + C>A + D>A +
3017             E>A. The row scores and column scores
3018             for choices B, C, D, and E are calculated
3019             similarly.
3020              
3021             Next, all the row scores are compared to
3022             determine which choice has the largest row
3023             score. In this example that score
3024             would be the row score for choice A (because it
3025             is first in alphabetical order).
3026             Therefore choice A is moved into first
3027             place. The other choices remain in the
3028             same order. The resulting sequence is A,
3029             C, E, D, B. Here is the pairwise matrix
3030             for the new sequence. The pairwise counts
3031             for the ranked choice (A) are surrounded by
3032             asterisks:
3033              
3034             | | | | | |
3035             | A | C | E | D | B |
3036             | | | | | |
3037             -----*****************************************
3038             * \ | | | | *
3039             A * \ | A>C | A>E | A>D | A>B *
3040             * \ | | | | *
3041             -----*-------*********************************
3042             * * \ | | | |
3043             C * C>A * \ | C>E | C>D | C>B |
3044             * * \ | | | |
3045             -----*-------*-------+-------+-------+-------+
3046             * * | \ | | |
3047             E * E>A * E>C | \ | E>D | E>B |
3048             * * | \ | | |
3049             -----*-------*-------+-------+-------+-------+
3050             * * | | \ | |
3051             D * D>A * D>C | D>E | \ | D>B |
3052             * * | | \ | |
3053             -----*-------*-------+-------+-------+-------+
3054             * * | | | \ |
3055             B * B>A * B>C | B>E | B>D | \ |
3056             * * | | | \ |
3057             -----*********-------+-------+-------+-------+
3058              
3059             The row scores and column scores for the
3060             remaining (unranked) choices are adjusted to
3061             remove the pairwise counts that involve the
3062             just-ranked choice (A). The removed
3063             pairwise counts are the ones surrounded by
3064             asterisks. Specifically, after
3065             subtracting B>A, the row score for choice B
3066             becomes B>C + B>D + B>E, and after
3067             subtracting A>B, the column score for choice
3068             B becomes C>B + D>B + E>B.
3069              
3070             From among the remaining row scores the
3071             highest score is found. At this point
3072             let's assume that both choice B and choice C
3073             have the same highest row score.
3074              
3075             In the case of a row-score tie, the
3076             choice with the smallest column score --
3077             from among the choices that have the same
3078             largest row score -- is ranked
3079             next. This would be choice B.
3080             Therefore, choice B is moved to the sequence
3081             position just after choice A. The
3082             resulting sequence is A, B, C, E, D.
3083             Below is the pairwise matrix for the new
3084             sequence. The pairwise counts for the
3085             ranked choices are surrounded by asterisks.
3086              
3087             | | | | | |
3088             | A | B | C | E | D |
3089             | | | | | |
3090             -----*****************************************
3091             * \ | | | | *
3092             A * \ | A>B | A>C | A>E | A>D *
3093             * \ | | | | *
3094             -----*-------+-------+-------+-------+-------*
3095             * | \ | | | *
3096             B * B>A | \ | B>C | B>E | B>D *
3097             * | \ | | | *
3098             -----*-------+--------************************
3099             * | * \ | | |
3100             C * C>A | C>B * \ | C>E | C>D |
3101             * | * \ | | |
3102             -----*-------+-------*-------+-------+-------+
3103             * | * | \ | |
3104             E * E>A | E>B * E>C | \ | E>D |
3105             * | * | \ | |
3106             -----*-------+-------*-------+-------+-------+
3107             * | * | | \ |
3108             D * D>A | D>B * D>C | D>E | \ |
3109             * | * | | \ |
3110             -----*****************-------+-------+-------+
3111              
3112             The same ranking process is repeated.
3113             The next choice to be ranked would be choice
3114             C. It would have the highest row score
3115             -- and the smallest column score if there is a
3116             row-score tie. So choice C would be
3117             identifed as the next choice in the ranked
3118             sequence. After that, choice D would
3119             have the highest row score, and would be ranked
3120             next. Finally the only remaining choice,
3121             choice E, would be ranked at the last (lowest)
3122             position.
3123              
3124             Here is the final pairwise matrix.
3125              
3126             | | | | | |
3127             | A | B | C | D | E |
3128             | | | | | |
3129             -----*****************************************
3130             * \ | | | | *
3131             A * \ | A>B | A>C | A>D | A>E *
3132             * \ | | | | *
3133             -----*-------+-------+-------+-------+-------*
3134             * | \ | | | *
3135             B * B>A | \ | B>C | B>D | B>E *
3136             * | \ | | | *
3137             -----*-------+-------+-------+-------+-------*
3138             * | | \ | | *
3139             C * C>A | C>B | \ | C>D | C>E *
3140             * | | \ | | *
3141             -----*-------+-------+-------+-------+-------*
3142             * | | | \ | *
3143             D * D>A | D>B | D>C | \ | D>E *
3144             * | | | \ | *
3145             -----*-------+-------+-------+-------+-------*
3146             * | | | | \ *
3147             E * E>A | E>B | E>C | E>D | \ *
3148             * | | | | \ *
3149             -----*****************************************
3150              
3151             The choices are now fully ranked according
3152             to the Choice-Specific Pairwise-Count
3153             method.
3154              
3155             If only a single winner is needed, the
3156             first-ranked choice should not necessarily be
3157             selected as the winner. Instead, the
3158             pairwise counts should be checked for a
3159             possible Condorcet winner, which may be second
3160             or third in the CSPS ranking result.
3161              
3162             Concise description of the calculation method:
3163              
3164             A row score and a column score
3165             is calculated for each choice. The
3166             row score is the sum of the pairwise counts in
3167             which the specified choice is preferred over
3168             each of the other choices. The column
3169             score is the sum of the pairwise counts in
3170             which each other choice is preferred over the
3171             specified choice.
3172              
3173             For the choices that have not yet been
3174             ranked, all the row scores are compared to find
3175             the highest row score. The choice
3176             that has the highest row score is moved to the
3177             most-popular or next-most popular position in
3178             the ranking results.
3179              
3180             If more than one choice is
3181             tied with the highest row score, the
3182             choice with the smallest column score is
3183             chosen. If more than one choice has the
3184             same row score and the same column score, the
3185             choices are regarded as tied.
3186              
3187             After each choice has been ranked, the
3188             scores for the remaining (unranked) choices are
3189             adjusted by subtracting from all the
3190             remaining scores the pairwise counts that
3191             involve the just-ranked choice.
3192              
3193             The process of ranking each choice and
3194             adjusting the remaining scores is
3195             repeated until only one choice remains,
3196             and it is ranked in the bottom (least-popular)
3197             position.
3198              
3199             (This description of the VoteFair choice-specific
3200             pairwise-score method was copied from
3201             www.VoteFair.org with permission.)
3202              
3203             =cut
3204              
3205             #-----------------------------------------------
3206             #-----------------------------------------------
3207             # calc_votefair_choice_specific_pairwise_score_popularity_rank
3208             #-----------------------------------------------
3209             #-----------------------------------------------
3210              
3211             sub calc_votefair_choice_specific_pairwise_score_popularity_rank
3212             {
3213              
3214 84     84 1 217 my $adjusted_choice ;
3215             my $adjusted_first_choice ;
3216 0         0 my $adjusted_second_choice ;
3217 0         0 my $adjusted_choice_being_displaced ;
3218 0         0 my $adjusted_choice_with_largest_score ;
3219 0         0 my $adjusted_choice_not_yet_sorted ;
3220 0         0 my $actual_choice ;
3221 0         0 my $actual_first_choice ;
3222 0         0 my $actual_second_choice ;
3223 0         0 my $actual_choice_with_largest_score ;
3224 0         0 my $actual_choice_not_yet_sorted ;
3225 0         0 my $actual_choice_being_displaced ;
3226 0         0 my $sequence_position ;
3227 0         0 my $new_position_of_choice_being_moved ;
3228 0         0 my $previous_position_of_choice_being_moved ;
3229 0         0 my $sequence_position_of_choice_not_yet_sorted ;
3230 0         0 my $ranking_level ;
3231 0         0 my $main_loop_count ;
3232 0         0 my $pair_counter ;
3233 0         0 my $tally_first_over_second ;
3234 0         0 my $tally_second_over_first ;
3235 0         0 my $row_score ;
3236 0         0 my $column_score ;
3237 0         0 my $largest_row_score ;
3238 0         0 my $smallest_column_score ;
3239 0         0 my $largest_column_score ;
3240 0         0 my $row_score_reduction ;
3241 0         0 my $column_score_reduction ;
3242 0         0 my $count_of_choices_sorted ;
3243 0         0 my $true_or_false_log_details ;
3244 0         0 my $count_of_tied_scores ;
3245 0         0 my $difference_between_tallies ;
3246 0         0 my $largest_positive_difference ;
3247 0         0 my $list_pointer ;
3248 0         0 my $tie_count_limit ;
3249 0         0 my $first_pointer ;
3250 0         0 my $second_pointer ;
3251              
3252 0         0 my @row_score_for_adjusted_choice ;
3253 0         0 my @column_score_for_adjusted_choice ;
3254 0         0 my @position_in_sequence_for_adjusted_choice ;
3255 0         0 my @adjusted_choice_in_rank_sequence_position ;
3256 0         0 my @adjusted_choice_at_tie_count ;
3257              
3258              
3259             #-----------------------------------------------
3260             # Hide or show the details in the log file.
3261              
3262 84         132 $true_or_false_log_details = $global_true ;
3263 84 50       213 if ( $global_logging_info == $global_true )
3264             {
3265 84         145 print LOGOUT "[choice-score, beginning calc_votefair_choice_specific_pairwise_score_popularity_rank subroutine]\n\n" ;
3266 84 50       193 if ( $true_or_false_log_details == $global_true )
3267             {
3268 84         131 print LOGOUT "[choice-score, details shown (change flag value to hide details)]\n" ;
3269             } else
3270             {
3271 0         0 print LOGOUT "[choice-score, details hidden (change flag value to view details)]\n" ;
3272             }
3273             }
3274              
3275              
3276             #-----------------------------------------------
3277             # Initialize the scale value for the logged
3278             # pairwise counts.
3279              
3280 84         96 $global_scale_for_logged_pairwise_counts = 1.0 ;
3281              
3282              
3283             #-----------------------------------------------
3284             # Initialize the results in case of an early
3285             # exit.
3286              
3287 84         224 for ( $adjusted_choice = 1 ; $adjusted_choice < $global_adjusted_choice_count ; $adjusted_choice ++ )
3288             {
3289 391         541 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
3290 391         821 $global_choice_score_popularity_rank_for_actual_choice[ $actual_choice ] = 0 ;
3291             }
3292              
3293              
3294             #-----------------------------------------------
3295             # If there are not at least two choices,
3296             # indicate an error.
3297              
3298 84 50       230 if ( $global_adjusted_choice_count < 2 )
3299             {
3300 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, ERROR: number of (adjusted) choices is less than two]\n" } ;
  0         0  
3301 0         0 return ;
3302             }
3303              
3304              
3305             #-----------------------------------------------
3306             # Initialize the choice sequence. Just use
3307             # numerical order. Also initialize other
3308             # values.
3309              
3310 84         279 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
3311             {
3312 475         493 $sequence_position = $adjusted_choice ;
3313 475         624 $adjusted_choice_in_rank_sequence_position[ $sequence_position ] = $adjusted_choice ;
3314 475         607 $position_in_sequence_for_adjusted_choice[ $adjusted_choice ] = $sequence_position ;
3315 475         512 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
3316 475         1008 $global_choice_score_popularity_rank_for_actual_choice[ $actual_choice ] = 0 ;
3317             }
3318 84         109 $adjusted_choice_with_largest_score = 0 ;
3319 84         108 $global_top_choice_according_to_choice_specific_scores = 0 ;
3320 84         118 $global_sequence_score_using_choice_score_method = 0 ;
3321              
3322              
3323             #-----------------------------------------------
3324             # Initialize the value that keeps track of how many
3325             # choices are in the group of highest-ranked
3326             # choices.
3327              
3328 84         156 $count_of_choices_sorted = 0 ;
3329              
3330              
3331             #-----------------------------------------------
3332             # For debugging, display the tally numbers in
3333             # an array/matrix arrangement.
3334              
3335 84 50       216 if ( $true_or_false_log_details == $global_true )
3336             {
3337 84         220 for ( $sequence_position = 1 ; $sequence_position <= $global_adjusted_choice_count ; $sequence_position ++ )
3338             {
3339 475         554 $adjusted_choice = $adjusted_choice_in_rank_sequence_position[ $sequence_position ] ;
3340 475         483 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
3341 475         1056 $global_log_info_choice_at_position[ $sequence_position ] = $actual_choice ;
3342             }
3343 84         143 print LOGOUT "[choice-score, initial ranking:]\n" ;
3344 84         145 &internal_view_matrix( ) ;
3345             }
3346              
3347              
3348             #-----------------------------------------------
3349             # Sum the tally counts in each column and each
3350             # row.
3351             # (The position of each choice in the
3352             # array/matrix does not affect these sums.)
3353             # The "pair counter" is an index that accesses
3354             # each combination of (adjusted) choice
3355             # numbers, where the first choice number is
3356             # less than the second choice number.
3357             # As a visual representation this means that
3358             # the pairwise tallies (counts) for the
3359             # upper-right diagonal and the lower-left
3360             # diagonal (triangular areas of the pairwise
3361             # matrix) are stored in the
3362             # global_tally_first_over_second_in_pair
3363             # and
3364             # global_tally_second_over_first_in_pair
3365             # lists (not necessarily respectively).
3366              
3367 84         246 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
3368             {
3369 475         544 $row_score_for_adjusted_choice[ $adjusted_choice ] = 0 ;
3370 475         1081 $column_score_for_adjusted_choice[ $adjusted_choice ] = 0 ;
3371             }
3372 84         260 for ( $pair_counter = 1 ; $pair_counter <= $global_pair_counter_maximum ; $pair_counter ++ )
3373             {
3374 1346         1563 $adjusted_first_choice = $global_adjusted_first_choice_number_in_pair[ $pair_counter ] ;
3375 1346         1413 $adjusted_second_choice = $global_adjusted_second_choice_number_in_pair[ $pair_counter ] ;
3376 1346         1646 $row_score_for_adjusted_choice[ $adjusted_first_choice ] += $global_tally_first_over_second_in_pair[ $pair_counter ] ;
3377 1346         1417 $row_score_for_adjusted_choice[ $adjusted_second_choice ] += $global_tally_second_over_first_in_pair[ $pair_counter ] ;
3378 1346         1520 $column_score_for_adjusted_choice[ $adjusted_first_choice ] += $global_tally_second_over_first_in_pair[ $pair_counter ] ;
3379 1346         1408 $column_score_for_adjusted_choice[ $adjusted_second_choice ] += $global_tally_first_over_second_in_pair[ $pair_counter ] ;
3380 1346         1524 $actual_first_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_first_choice ] ;
3381 1346         1371 $actual_second_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_second_choice ] ;
3382 1346 50       2317 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, for first choice " . $actual_first_choice . " and second choice " . $actual_second_choice . " , tally first over second is " . $global_tally_first_over_second_in_pair[ $pair_counter ] . " , and tally second over first is " . $global_tally_second_over_first_in_pair[ $pair_counter ] . "]\n" } ;
  1346         6914  
3383             }
3384              
3385              
3386             #-----------------------------------------------
3387             # Display (in the log file) the current column
3388             # and row scores. Also save the largest
3389             # column score.
3390              
3391 84         152 $largest_column_score = 0 ;
3392 84 50       228 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, current column and row scores:]\n" } ;
  84         221  
3393 84         216 for ( $sequence_position = $count_of_choices_sorted + 1 ; $sequence_position <= $global_adjusted_choice_count ; $sequence_position ++ )
3394             {
3395 475         538 $adjusted_choice = $adjusted_choice_in_rank_sequence_position[ $sequence_position ] ;
3396 475         565 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
3397 475 50       6771 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[ for choice " . $actual_choice . " row score is " . $row_score_for_adjusted_choice[ $adjusted_choice ] . " and column score is " . $column_score_for_adjusted_choice[ $adjusted_choice ] . "]\n" } ;
  475         1597  
3398 475 100       1433 if ( $column_score_for_adjusted_choice[ $adjusted_choice ] > $largest_column_score )
3399             {
3400 176         445 $largest_column_score = $column_score_for_adjusted_choice[ $adjusted_choice ] ;
3401             }
3402             }
3403 84 50       211 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "\n" } ;
  84         120  
3404              
3405              
3406             #-----------------------------------------------
3407             # Begin a loop that identifies which choice
3408             # to move into the first/next-highest or
3409             # last/lowest sequence position.
3410             # The loop is exited in the middle (not here).
3411              
3412 84         113 $main_loop_count = 0 ;
3413 84         206 while ( $main_loop_count < $global_adjusted_choice_count + 10 )
3414             {
3415 475         536 $main_loop_count ++ ;
3416              
3417              
3418             #-----------------------------------------------
3419             # Prevent an endless loop.
3420              
3421 475 50       1096 if ( $main_loop_count > 10000 )
3422             {
3423 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, loop counter has exceeded limit, probably because the choice count (" . $global_full_choice_count . ") is so large, so exiting choice-score rank]" } ;
  0         0  
3424 0         0 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
3425             {
3426 0         0 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
3427 0         0 $global_choice_score_popularity_rank_for_actual_choice[ $actual_choice ] = 0 ;
3428             }
3429 0         0 last ;
3430             }
3431              
3432              
3433             #-----------------------------------------------
3434             # If there is only one choice remaining, rank
3435             # it at the middle, between the two sorted lists.
3436              
3437 475 100       982 if ( $count_of_choices_sorted + 1 == $global_adjusted_choice_count )
3438             {
3439 84         151 $adjusted_choice = $adjusted_choice_in_rank_sequence_position[ $count_of_choices_sorted + 1 ] ;
3440 84         136 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
3441 84         138 $global_choice_score_popularity_rank_for_actual_choice[ $actual_choice ] = $count_of_choices_sorted + 1 ;
3442 84 50       177 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, no choices unsorted, so done sorting]\n" } ;
  84         124  
3443 84         175 last ;
3444             }
3445              
3446              
3447             #-----------------------------------------------
3448             # If all the choices have been sorted, exit
3449             # the loop.
3450              
3451 391 50       779 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, most-popular sorted list length is " . $count_of_choices_sorted . "]\n" } ;
  391         986  
3452 391 50       828 if ( $count_of_choices_sorted >= $global_adjusted_choice_count )
3453             {
3454 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, no choices unsorted, so done sorting]\n" } ;
  0         0  
3455 0         0 last ;
3456             }
3457              
3458              
3459             #-----------------------------------------------
3460             # Identify which choice has the largest
3461             # choice-specific score-based row score.
3462             # If there is a tie between row scores,
3463             # choose the choice with the smallest
3464             # column score. If there are multiple tied
3465             # choices, save those choice numbers in a list.
3466              
3467 391         449 $largest_row_score = -1 ;
3468 391         491 $smallest_column_score = $largest_column_score ;
3469 391         432 $adjusted_choice_with_largest_score = 0 ;
3470 391         451 $count_of_tied_scores = 0 ;
3471 391         1031 for ( $sequence_position = $count_of_choices_sorted + 1 ; $sequence_position <= $global_adjusted_choice_count ; $sequence_position ++ )
3472             {
3473 1737         1959 $adjusted_choice = $adjusted_choice_in_rank_sequence_position[ $sequence_position ] ;
3474 1737         1968 $row_score = $row_score_for_adjusted_choice[ $adjusted_choice ] ;
3475 1737         1930 $column_score = $column_score_for_adjusted_choice[ $adjusted_choice ] ;
3476 1737 100 100     7902 if ( ( $row_score > $largest_row_score ) || ( ( $row_score == $largest_row_score ) && ( $column_score < $smallest_column_score ) ) )
    100 66        
3477             {
3478 738         796 $adjusted_choice_with_largest_score = $adjusted_choice ;
3479 738         780 $largest_row_score = $row_score ;
3480 738         697 $smallest_column_score = $column_score ;
3481 738         777 $count_of_tied_scores = 1 ;
3482 738         839 $adjusted_choice_at_tie_count[ $count_of_tied_scores ] = $adjusted_choice_with_largest_score ;
3483 738         843 $actual_choice_with_largest_score = $global_actual_choice_for_adjusted_choice[ $adjusted_choice_with_largest_score ] ;
3484 738 50       1305 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, starting new tied list, adding to tied list, choice " . $actual_choice_with_largest_score . " (row score is " . $largest_row_score . " and column score is " . $smallest_column_score . ")]\n" } ;
  738         3361  
3485             } elsif ( $row_score == $largest_row_score )
3486             {
3487 109         142 $adjusted_choice_with_largest_score = $adjusted_choice ;
3488 109         413 $count_of_tied_scores ++ ;
3489 109         150 $adjusted_choice_at_tie_count[ $count_of_tied_scores ] = $adjusted_choice_with_largest_score ;
3490 109         168 $actual_choice_with_largest_score = $global_actual_choice_for_adjusted_choice[ $adjusted_choice_with_largest_score ] ;
3491 109 50       218 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, adding to tied list, choice " . $actual_choice_with_largest_score . " (row score is " . $largest_row_score . " and column score is " . $smallest_column_score . ")]\n" } ;
  109         453  
3492             }
3493             }
3494              
3495              
3496             #-----------------------------------------------
3497             # Specify the limit for the number of tied
3498             # choices for which it is worth the time to
3499             # see if the choices with the same highest scores
3500             # can be sorted. This number should NOT
3501             # exceed about 5 at the most. If it is one,
3502             # the lowest-numbered choice will be sorted
3503             # into the next position.
3504              
3505 391         468 $tie_count_limit = 1 ;
3506 391 50       815 if ( $tie_count_limit < 1 )
3507             {
3508 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[ERROR: choice-score, tie_count_limit (" . $count_of_tied_scores . ") is too small]\n" } ;
  0         0  
3509 0         0 die "value of tie_count_limit is too small" ;
3510             }
3511              
3512              
3513             #-----------------------------------------------
3514             # If only one choice has the highest score,
3515             # save it, and skip over the next sections
3516             # that deal with ties.
3517             # If this choice is the highest-ranked choice,
3518             # make it available for possible tie-breaking
3519             # use in the insertion-sort calculations.
3520              
3521 391 100       732 if ( $count_of_tied_scores == 1 )
    50          
3522             {
3523 317         381 $adjusted_choice_at_tie_count[ $count_of_tied_scores ] = $adjusted_choice_with_largest_score ;
3524 317         427 $actual_choice_with_largest_score = $global_actual_choice_for_adjusted_choice[ $adjusted_choice_with_largest_score ] ;
3525 317 100       701 if ( $count_of_choices_sorted == 0 )
3526             {
3527 77         148 $global_top_choice_according_to_choice_specific_scores = $actual_choice_with_largest_score ;
3528             }
3529 317 50       610 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, no tie, only choice " . $actual_choice_with_largest_score . "]\n" } ;
  317         815  
3530 317 50       633 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, choice " . $actual_choice_with_largest_score . " has largest row score " . $largest_row_score . " (and a possible tie-breaking column score of " . $smallest_column_score . ")]\n" } ;
  317         897  
3531              
3532              
3533             #-----------------------------------------------
3534             # If there are too many tied choices, pick the
3535             # first one as the next choice to sort.
3536             # Keep in mind that this algorithm estimates
3537             # the ranking, and depends on the
3538             # insertion-sort algorithm to refine the exact
3539             # ranking. Also, the method of resolving a
3540             # tie (below) is not always correct.
3541              
3542             } elsif ( $count_of_tied_scores > $tie_count_limit )
3543             {
3544 74         96 $count_of_tied_scores = 1 ;
3545 74 50       159 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, there is a tie among " . $count_of_tied_scores . " choices, which is too many, so only choice " . $adjusted_choice_at_tie_count[ $count_of_tied_scores ] . " is picked]\n" } ;
  74         261  
3546              
3547              
3548             #-----------------------------------------------
3549             # If more than one choice has the same highest
3550             # row score, without a tie-breaking column score,
3551             # begin to identify which
3552             # choice has the best (highest) pairwise
3553             # comparison with each of the other tied
3554             # choices.
3555              
3556             } else
3557             {
3558 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, tie involving " . $count_of_tied_scores . " choices]\n" } ;
  0         0  
3559              
3560              
3561             #-----------------------------------------------
3562             # For each pair of tied choices, calculate the
3563             # difference between the relevant pairwise
3564             # counts (tally numbers), and identify the
3565             # largest such difference, and choose to sort
3566             # the choice that is associated with the
3567             # largest positive difference.
3568              
3569 0         0 $largest_positive_difference = 0 ;
3570 0         0 for ( $first_pointer = 1 ; $first_pointer < $count_of_tied_scores ; $first_pointer ++ )
3571             {
3572 0         0 $adjusted_first_choice = $adjusted_choice_at_tie_count[ $first_pointer ] ;
3573 0         0 $actual_first_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_first_choice ] ;
3574 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, first choice is " . $actual_first_choice . "]\n" } ;
  0         0  
3575 0         0 for ( $second_pointer = $first_pointer + 1 ; $second_pointer <= $count_of_tied_scores ; $second_pointer ++ )
3576             {
3577 0         0 $adjusted_second_choice = $adjusted_choice_at_tie_count[ $second_pointer ] ;
3578 0         0 $actual_second_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_second_choice ] ;
3579 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, second choice is " . $actual_second_choice . "]\n" } ;
  0         0  
3580 0         0 $pair_counter = $global_pair_counter_offset_for_first_adjusted_choice[ $adjusted_first_choice ] + $adjusted_second_choice ;
3581 0         0 $tally_first_over_second = $global_tally_first_over_second_in_pair[ $pair_counter ] ;
3582 0         0 $tally_second_over_first = $global_tally_second_over_first_in_pair[ $pair_counter ] ;
3583 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, first tied choice " . $actual_first_choice . " and second tied choice " . $actual_second_choice . " have tallies " . $tally_first_over_second . " and " . $tally_second_over_first . "]\n" } ;
  0         0  
3584 0         0 $difference_between_tallies = $tally_first_over_second - $tally_second_over_first ;
3585 0 0       0 if ( $difference_between_tallies > 0 )
    0          
3586             {
3587 0 0       0 if ( $difference_between_tallies > $largest_positive_difference )
    0          
3588             {
3589 0         0 $largest_positive_difference = $difference_between_tallies ;
3590 0         0 $count_of_tied_scores = 1 ;
3591 0         0 $adjusted_choice_at_tie_count[ $count_of_tied_scores ] = $adjusted_first_choice ;
3592 0         0 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_first_choice ] ;
3593 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, choice " . $actual_choice . " is first choice chosen so far]\n" } ;
  0         0  
3594             } elsif ( $difference_between_tallies == $largest_positive_difference )
3595             {
3596 0         0 $count_of_tied_scores ++ ;
3597 0         0 $adjusted_choice_at_tie_count[ $count_of_tied_scores ] = $adjusted_first_choice ;
3598 0         0 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_first_choice ] ;
3599 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, choice " . $actual_choice . " is added to list as chosen so far]\n" } ;
  0         0  
3600             }
3601             } elsif ( $difference_between_tallies < 0 )
3602             {
3603 0 0       0 if ( ( - $difference_between_tallies ) > $largest_positive_difference )
    0          
3604             {
3605 0         0 $largest_positive_difference = - $difference_between_tallies ;
3606 0         0 $count_of_tied_scores = 1 ;
3607 0         0 $adjusted_choice_at_tie_count[ $count_of_tied_scores ] = $adjusted_second_choice ;
3608 0         0 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_second_choice ] ;
3609 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, choice " . $actual_choice . " is first choice chosen so far]\n" } ;
  0         0  
3610             } elsif ( ( - $difference_between_tallies ) == $largest_positive_difference )
3611             {
3612 0         0 $count_of_tied_scores ++ ;
3613 0         0 $largest_positive_difference = - $difference_between_tallies ;
3614 0         0 $adjusted_choice_at_tie_count[ $count_of_tied_scores ] = $adjusted_second_choice ;
3615 0         0 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_second_choice ] ;
3616 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, choice " . $actual_choice . " is added to list as chosen so far]\n" } ;
  0         0  
3617             }
3618             } else
3619             {
3620 0         0 $largest_positive_difference = 0 ;
3621 0         0 $count_of_tied_scores ++ ;
3622 0         0 $adjusted_choice_at_tie_count[ $count_of_tied_scores ] = $adjusted_first_choice ;
3623 0         0 $count_of_tied_scores ++ ;
3624 0         0 $adjusted_choice_at_tie_count[ $count_of_tied_scores ] = $adjusted_second_choice ;
3625 0         0 $actual_first_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_first_choice ] ;
3626 0         0 $actual_second_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_second_choice ] ;
3627 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, tie at zero, so both choices " . $actual_first_choice . " and " . $actual_second_choice . " are chosen so far]\n" } ;
  0         0  
3628             }
3629 0         0 $main_loop_count ++ ;
3630 0 0       0 if ( $main_loop_count > 10000 )
3631             {
3632 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, loop counter has exceeded limit while handling tied scores, which means the value of tie_count_limit (which is " . $tie_count_limit . ") is too large ]" } ;
  0         0  
3633 0         0 last ;
3634             }
3635             }
3636             }
3637              
3638              
3639             #-----------------------------------------------
3640             # Terminate the branches that handle situations
3641             # in which more than one choice has the same highest
3642             # row score (and the lowest column score if there
3643             # is a tie in the row scores).
3644              
3645 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, will repeat loop if another tied choice]\n" } ;
  0         0  
3646             }
3647              
3648              
3649             #-----------------------------------------------
3650             # Specify the ranking level.
3651              
3652 391         570 $ranking_level = $count_of_choices_sorted + 1 ;
3653 391 50       765 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, ranking level is " . $ranking_level . "]\n" } ;
  391         730  
3654              
3655              
3656             #-----------------------------------------------
3657             # Begin a loop that repeats only if there are
3658             # multiple choices that are tied at the same
3659             # ranking level, in which case the loop
3660             # repeats for each such choice. Otherwise this
3661             # loop is executed only once.
3662              
3663 391         921 for ( $list_pointer = 1 ; $list_pointer <= $count_of_tied_scores ; $list_pointer ++ )
3664             {
3665 391         457 $adjusted_choice_with_largest_score = $adjusted_choice_at_tie_count[ $list_pointer ] ;
3666 391         472 $actual_choice_with_largest_score = $global_actual_choice_for_adjusted_choice[ $adjusted_choice_with_largest_score ] ;
3667 391 50       744 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, next-ranked choice is " . $actual_choice_with_largest_score . "]\n" } ;
  391         736  
3668              
3669              
3670             #-----------------------------------------------
3671             # Rank the specified choice at the current ranking
3672             # level.
3673              
3674 391         519 $global_choice_score_popularity_rank_for_actual_choice[ $actual_choice_with_largest_score ] = $ranking_level ;
3675 391 50       784 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, choice " . $actual_choice_with_largest_score . " ranked at level " . $ranking_level . "]\n" } ;
  391         875  
3676              
3677              
3678             #-----------------------------------------------
3679             # Move the specified choice to the bottom of
3680             # the highest-ranked choices.
3681             # To make room in the sequence, move
3682             # whichever choice is already there.
3683             # If the choice is already in the correct
3684             # row and column, skip ahead.
3685              
3686 391         433 $count_of_choices_sorted ++ ;
3687 391         540 $new_position_of_choice_being_moved = $count_of_choices_sorted ;
3688 391         453 $previous_position_of_choice_being_moved = $position_in_sequence_for_adjusted_choice[ $adjusted_choice_with_largest_score ] ;
3689 391 50       730 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, moving choice " . $actual_choice_with_largest_score . " from position " . $previous_position_of_choice_being_moved . " to position " . $new_position_of_choice_being_moved . "]\n" } ;
  391         975  
3690 391 100       718 if ( $new_position_of_choice_being_moved != $previous_position_of_choice_being_moved )
3691             {
3692 248         298 $adjusted_choice_being_displaced = $adjusted_choice_in_rank_sequence_position[ $new_position_of_choice_being_moved ] ;
3693 248         278 $actual_choice_being_displaced = $global_actual_choice_for_adjusted_choice[ $adjusted_choice_being_displaced ] ;
3694              
3695 248         297 $adjusted_choice_in_rank_sequence_position[ $new_position_of_choice_being_moved ] = $adjusted_choice_with_largest_score ;
3696              
3697 248         362 $position_in_sequence_for_adjusted_choice[ $adjusted_choice_with_largest_score ] = $new_position_of_choice_being_moved ;
3698              
3699 248         274 $adjusted_choice_in_rank_sequence_position[ $previous_position_of_choice_being_moved ] = $adjusted_choice_being_displaced ;
3700              
3701 248         380 $position_in_sequence_for_adjusted_choice[ $adjusted_choice_being_displaced ] = $previous_position_of_choice_being_moved ;
3702              
3703             } else
3704             {
3705 143 50       324 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, no move needed]" . "\n" } ;
  143         347  
3706              
3707             }
3708              
3709 391 50       799 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "\n" } ;
  391         621  
3710              
3711              
3712             #-----------------------------------------------
3713             # For debugging, display the tally numbers in
3714             # an array/matrix arrangement.
3715              
3716 391 50       786 if ( $true_or_false_log_details == $global_true )
3717             {
3718 391         905 for ( $sequence_position = 1 ; $sequence_position <= $global_adjusted_choice_count ; $sequence_position ++ )
3719             {
3720 2692         2890 $adjusted_choice = $adjusted_choice_in_rank_sequence_position[ $sequence_position ] ;
3721 2692         2649 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
3722 2692         5629 $global_log_info_choice_at_position[ $sequence_position ] = $actual_choice ;
3723             }
3724 391         671 print LOGOUT "[choice-score, intermediate ranking:]\n" ;
3725 391         3225 &internal_view_matrix( ) ;
3726             }
3727 391         670 $global_sequence_score_using_choice_score_method = $global_sequence_score ;
3728              
3729              
3730             #-----------------------------------------------
3731             # Skip ahead if the last choice has been sorted.
3732              
3733 391 50       860 if ( $count_of_choices_sorted < $global_adjusted_choice_count )
3734             {
3735              
3736              
3737             #-----------------------------------------------
3738             # Reduce each row score and each column score by
3739             # the pairwise counts that are associated with
3740             # the choice that was just sorted. This
3741             # updates the row and column scores to apply to
3742             # only the unsorted choices.
3743             # In case the number of choices is large (such
3744             # as hundreds of choices), access the tally
3745             # counts efficiently (and without creating an
3746             # extra array that converts from choice-number
3747             # combinations into pair numbers).
3748              
3749 391         867 for ( $sequence_position_of_choice_not_yet_sorted = $count_of_choices_sorted + 1 ; $sequence_position_of_choice_not_yet_sorted <= $global_adjusted_choice_count ; $sequence_position_of_choice_not_yet_sorted ++ )
3750             {
3751 1346         1606 $adjusted_choice_not_yet_sorted = $adjusted_choice_in_rank_sequence_position[ $sequence_position_of_choice_not_yet_sorted ] ;
3752 1346 100       2064 if ( $adjusted_choice_with_largest_score < $adjusted_choice_not_yet_sorted )
3753             {
3754 672         841 $pair_counter = $global_pair_counter_offset_for_first_adjusted_choice[ $adjusted_choice_with_largest_score ] + $adjusted_choice_not_yet_sorted ;
3755 672         771 $column_score_reduction = $global_tally_first_over_second_in_pair[ $pair_counter ] ;
3756 672         904 $row_score_reduction = $global_tally_second_over_first_in_pair[ $pair_counter ] ;
3757             } else
3758             {
3759 674         815 $pair_counter = $global_pair_counter_offset_for_first_adjusted_choice[ $adjusted_choice_not_yet_sorted ] + $adjusted_choice_with_largest_score ;
3760 674         807 $row_score_reduction = $global_tally_first_over_second_in_pair[ $pair_counter ] ;
3761 674         907 $column_score_reduction = $global_tally_second_over_first_in_pair[ $pair_counter ] ;
3762             }
3763 1346         1625 $actual_choice_not_yet_sorted = $global_actual_choice_for_adjusted_choice[ $adjusted_choice_not_yet_sorted ] ;
3764 1346         1934 $row_score_for_adjusted_choice[ $adjusted_choice_not_yet_sorted ] -= $row_score_reduction ;
3765 1346 50       2644 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, for choice " . $actual_choice_not_yet_sorted . " row score reduced by " . $row_score_reduction . "]\n" } ;
  1346         3563  
3766 1346         1477 $column_score_for_adjusted_choice[ $adjusted_choice_not_yet_sorted ] -= $column_score_reduction ;
3767 1346 50       2616 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, for choice " . $actual_choice_not_yet_sorted . " column score reduced by " . $column_score_reduction . "]\n" } ;
  1346         13143  
3768             }
3769              
3770              
3771             #-----------------------------------------------
3772             # Display the updated row and column scores.
3773              
3774 391 50       754 if ( $true_or_false_log_details == $global_true )
3775             {
3776 391         914 print LOGOUT "[choice-score, current row and column scores:]\n" ;
3777 391         834 for ( $sequence_position = $count_of_choices_sorted + 1 ; $sequence_position <= $global_adjusted_choice_count ; $sequence_position ++ )
3778             {
3779 1346         1605 $adjusted_choice = $adjusted_choice_in_rank_sequence_position[ $sequence_position ] ;
3780 1346         1367 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
3781 1346         5011 print LOGOUT "[ for choice " . $actual_choice . " row score is " . $row_score_for_adjusted_choice[ $adjusted_choice ] . " and column score is " . $column_score_for_adjusted_choice[ $adjusted_choice ] . "]\n" ;
3782             }
3783 391         1926 print LOGOUT "\n" ;
3784             }
3785              
3786              
3787             #-----------------------------------------------
3788             # Finish skipping ahead if the last choice has
3789             # been sorted.
3790              
3791             }
3792              
3793              
3794             #-----------------------------------------------
3795             # Repeat the loop that is repeated only if there
3796             # is a tie.
3797              
3798             }
3799              
3800              
3801             #-----------------------------------------------
3802             # Repeat the loop that identifies which choice to
3803             # sort next.
3804              
3805             }
3806              
3807              
3808             #-----------------------------------------------
3809             # Normalize the results.
3810              
3811 84         278 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
3812             {
3813 475         560 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
3814 475         1098 $global_rank_to_normalize_for_adjusted_choice[ $adjusted_choice ] = $global_choice_score_popularity_rank_for_actual_choice[ $actual_choice ] ;
3815             }
3816 84         204 &normalize_ranking( ) ;
3817 84 50       221 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, final normalized ranking levels]\n" } ;
  84         221  
3818 84         241 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
3819             {
3820 475         549 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
3821 475         499 $ranking_level = $global_rank_to_normalize_for_adjusted_choice[ $adjusted_choice ] ;
3822 475         537 $global_choice_score_popularity_rank_for_actual_choice[ $actual_choice ] = $ranking_level ;
3823 475 50       887 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, choice " . $actual_choice . " at normalized rank level " . $ranking_level . "]\n" } ;
  475         1911  
3824             }
3825              
3826              
3827             #-----------------------------------------------
3828             # Log the calculated ranking levels.
3829              
3830 84 50       188 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice-score, final results:]\n" } ;
  84         242  
3831 84         234 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
3832             {
3833 475         546 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
3834 475 50       865 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[ choice " . $actual_choice . " is at ranking level " . $global_choice_score_popularity_rank_for_actual_choice[ $actual_choice ] . "]\n" } ;
  475         1830  
3835             }
3836              
3837              
3838             #-----------------------------------------------
3839             # End of subroutine.
3840              
3841 84 50       240 if ( $global_logging_info == $global_true ) { print LOGOUT "[choice-score, exiting calc_votefair_choice_specific_pairwise_score_popularity_rank subroutine]\n\n" } ;
  84         332  
3842 84         493 return ;
3843              
3844             }
3845              
3846              
3847              
3848             =head2 calc_votefair_insertion_sort_popularity_rank
3849              
3850             (Not exported, for internal use only.)
3851              
3852             Calculates VoteFair popularity ranking results
3853             using the "insertion-sort" sorting algorithm.
3854              
3855             VoteFair popularity ranking is described in
3856             Wikipedia, and is mathematically equivalent
3857             to the Condorcet-Kemeny method. The
3858             following comments explain the algorithm used
3859             here, which quickly calculates the ranking
3860             results. This explanation is important
3861             because some academic sources claim that
3862             the computations cannot be done quickly if
3863             there is a large number of choices being
3864             ranked.
3865              
3866             Although the goal of VoteFair popularity
3867             ranking is to find the sequence that has the
3868             highest sequence score, the scores themselves
3869             do not need to be calculated. This
3870             concept is similar to not needing to know the
3871             elevation of every point in a region in order
3872             to know that a specific mountain peak is the
3873             highest elevation in that region. By not
3874             calculating all the sequence scores, the
3875             calculation time can be greatly reduced
3876             compared to the method that calculates all the
3877             sequence scores.
3878              
3879             The algorithm described here assumes that
3880             the choices already have been pre-sorted using
3881             the Choice-Specific Pairwise-Score (CSPS)
3882             algorithm. That algorithm is part of this
3883             full calculation algorithm.
3884              
3885             The full algorithm repeatedly uses a
3886             variation of the "insertion-sort" sorting
3887             algorithm, so that algorithm is described
3888             first.
3889              
3890             Insertion-sort algorithm applied to finding
3891             maximum sequence score:
3892              
3893             This explanation clarifies how the
3894             well-known insertion-sort algorithm is applied
3895             to VoteFair popularity ranking in a way that
3896             greatly reduces the number of calculations
3897             needed to find maximum sequence scores.
3898             (This method is just part of the full
3899             algorithm, which is explained in the next
3900             section.)
3901              
3902             Consider an example in which there are five
3903             choices named A, B, C, D, and E, with a final
3904             sort order that matches this alphabetical
3905             order.
3906              
3907             Notation: The notation A>B refers to how
3908             many voters pairwise prefer choice A over
3909             choice B, and the notation B>A refers to how
3910             many voters pairwise prefer choice B over
3911             choice A. This notation always uses the
3912             "greater-than" symbol ">", and never uses
3913             the "less-than" symbol "<".
3914              
3915             At an intermediate stage in this sorting
3916             example, suppose that the choices A, C, and E
3917             have been sorted -- into this correct
3918             order -- and choice B is about to be
3919             sorted, and choice D remains unsorted.
3920             The pairwise counts for this arrangement are
3921             shown below. The asterisks show the
3922             separation between sorted choices and unsorted
3923             choices.
3924              
3925             | | | | | |
3926             | A | C | E | B | D |
3927             | | | | | |
3928             -----*************************-------+-------+
3929             * \ | | * | |
3930             A * \ | A>C | A>E * A>B | A>D |
3931             * \ | | * | |
3932             -----+-------+-------+-------+-------+-------+
3933             * | \ | * | |
3934             C * C>A | \ | C>E * C>B | C>D |
3935             * | \ | * | |
3936             -----+-------+-------+-------+-------+-------+
3937             * | | \ * | |
3938             E * E>A | E>C | \ * E>B | E>D |
3939             * | | \ * | |
3940             -----*************************-------+-------+
3941             | | | | \ | |
3942             B | B>A | B>C | B>E | \ | B>D |
3943             | | | | \ | |
3944             -----+-------+-------+-------+-------+-------+
3945             | | | | | \ |
3946             D | D>A | D>C | D>E | D>B | \ |
3947             | | | | | \ |
3948             -----+-------+-------+-------+-------+-------+
3949              
3950             The diagonal line passes through empty cells
3951             -- that would otherwise represent a
3952             choice's comparison with itself, such as
3953             A>A.
3954              
3955             The diagonal line also is the border between
3956             the upper-right triangular area and the
3957             lower-left triangular area. The sequence
3958             score for the current sequence is the sum of
3959             all the pairwise counts in the upper-right
3960             triangular area (currently A>C + A>E +
3961             A>B + A>D + C>E + C>B + C>D +
3962             E>B + E>D + B>D).
3963              
3964             The goal of these calculations is to find
3965             the maximum sequence score, which means the
3966             goal is to change the sequence so that the
3967             largest pairwise counts move into the
3968             upper-right triangular area, leaving the
3969             smallest pairwise counts in the lower-left
3970             triangular area.
3971              
3972             The first step in sorting choice B is to
3973             consider the possibility of moving it to the
3974             left of choice E, which would form the sequence
3975             A, C, B, E. Here is the pairwise-count
3976             matrix for this sequence. The asterisks
3977             now include choice B because this is a possible
3978             sort order.
3979              
3980             | | | | | |
3981             | A | C | B | E | D |
3982             | | | | | |
3983             -----*********************************-------+
3984             * \ | | | * |
3985             A * \ | A>C | A>B | A>E * A>D |
3986             * \ | | | * |
3987             -----*-------+-------+-------+-------*-------+
3988             * | \ | | * |
3989             C * C>A | \ | C>B | C>E * C>D |
3990             * | \ | | * |
3991             -----*-------+-------+-------+-------*-------+
3992             * | | \ | * |
3993             B * B>A | B>C | \ | B>E * B>D |
3994             * | | \ | --- * |
3995             -----*-------+-------+-------+-------*-------+
3996             * | | | \ * |
3997             E * E>A | E>C | E>B | \ * E>D |
3998             * | | --- | \ * |
3999             -----*********************************-------+
4000             | | | | | \ |
4001             D | D>A | D>C | D>B | D>E | \ |
4002             | | | | | \ |
4003             -----+-------+-------+-------+-------+-------+
4004              
4005             The only pairwise counts that crossed the
4006             diagonal line are the (underlined) counts
4007             B>E and E>B, which swapped places.
4008             All the other pairwise counts that move do not
4009             cross the diagonal line; they stay on the same
4010             side of the diagonal line.
4011              
4012             As a result, the score for this sequence,
4013             compared to the score for the previous
4014             sequence, increases (or decreases if negative)
4015             by the amount B>E minus E>B. In
4016             this case (assuming there are no complications
4017             that are explained later) the sequence score
4018             has increased because in the final
4019             (alphabetical) sort order, choice B appears
4020             before choice E.
4021              
4022             The next step in sorting choice B is to
4023             consider the possibility of moving it to the
4024             left of choice C, which would form the sequence
4025             A, B, C, E. Here is the pairwise-count
4026             matrix for this sequence.
4027              
4028             | | | | | |
4029             | A | B | C | E | D |
4030             | | | | | |
4031             -----*********************************-------+
4032             * \ | | | * |
4033             A * \ | A>B | A>C | A>E * A>D |
4034             * \ | | | * |
4035             -----*-------+-------+-------+-------*-------+
4036             * | \ | | * |
4037             B * B>A | \ | B>C | B>E * B>D |
4038             * | \ | --- | * |
4039             -----*-------+-------+-------+-------*-------+
4040             * | | \ | * |
4041             C * C>A | C>B | \ | C>E * C>D |
4042             * | --- | \ | * |
4043             -----*-------+-------+-------+-------*-------+
4044             * | | | \ * |
4045             E * E>A | E>B | E>C | \ * E>D |
4046             * | | | \ * |
4047             -----*********************************-------+
4048             | | | | | \ |
4049             D | D>A | D>B | D>C | D>E | \ |
4050             | | | | | \ |
4051             -----+-------+-------+-------+-------+-------+
4052              
4053             The only pairwise counts that crossed the
4054             diagonal line are the (underlined) counts
4055             B>C and C>B, which swapped places.
4056             The other pairwise counts that moved remained
4057             on the same side of the diagonal line.
4058              
4059             The score for this sequence increases (or
4060             decreases if negative) by the amount B>C
4061             minus C>B. In this case the sequence
4062             score has increased because (in the final
4063             alphabetical order) choice B appears before
4064             choice C.
4065              
4066             The final step in sorting choice B is to
4067             consider the possibility of moving it to the
4068             left of choice A, which would form the sequence
4069             B, A, C, E. Here is the matrix for this
4070             sequence.
4071              
4072             | | | | | |
4073             | B | A | C | E | D |
4074             | | | | | |
4075             -----*********************************-------+
4076             * \ | | | * |
4077             B * \ | B>A | B>C | B>E * B>D |
4078             * \ | --- | | * |
4079             -----*-------+-------+-------+-------*-------+
4080             * | \ | | * |
4081             A * A>B | \ | A>C | A>E * A>D |
4082             * --- | \ | | * |
4083             -----*-------+-------+-------+-------*-------+
4084             * | | \ | * |
4085             C * C>B | C>A | \ | C>E * C>D |
4086             * | | \ | * |
4087             -----*-------+-------+-------+-------*-------+
4088             * | | | \ * |
4089             E * E>B | E>A | E>C | \ * E>D |
4090             * | | | \ * |
4091             -----*********************************-------+
4092             | | | | | \ |
4093             D | D>B | D>A | D>C | D>E | \ |
4094             | | | | | \ |
4095             -----+-------+-------+-------+-------+-------+
4096              
4097             The only pairwise counts that crossed the
4098             diagonal line are the (underlined) counts
4099             B>A and A>B, which swapped places.
4100             The other pairwise counts that moved remained
4101             on the same side of the diagonal line.
4102              
4103             The score for this sequence increases (or
4104             decreases if negative) by the amount B>A
4105             minus A>B. In this case the sequence
4106             score has decreased because (in the final
4107             alphabetical order) choice B appears after, not
4108             before, choice A.
4109              
4110             At this point choice B has been tested at
4111             each position within the sorted portion.
4112             The maximum sequence score (for the sorted
4113             portion) occurred when it was between choices A
4114             and C. As a result, choice B will be
4115             moved to the position between choices A and
4116             C.
4117              
4118             Notice that the full sequence score did not
4119             need to be calculated in order to find this
4120             "local" maximum. These calculations only
4121             need to keep track of increases and decreases
4122             that occur as the being-sorted choice swaps
4123             places with successive already-sorted
4124             choices.
4125              
4126             The pairwise-count matrix with choice B in
4127             the second sort-order position (between A and
4128             C) is shown below. Now choice D is the
4129             only unsorted choice.
4130              
4131             | | | | | |
4132             | A | B | C | E | D |
4133             | | | | | |
4134             -----*********************************-------+
4135             * \ | | | * |
4136             A * \ | A>B | A>C | A>E * A>D |
4137             * \ | | | * |
4138             -----*-------+-------+-------+-------*-------+
4139             * | \ | | * |
4140             B * B>A | \ | B>C | B>E * B>D |
4141             * | \ | | * |
4142             -----*-------+-------+-------+-------*-------+
4143             * | | \ | * |
4144             C * C>A | C>B | \ | C>E * C>D |
4145             * | | \ | * |
4146             -----*-------+-------+-------+-------*-------+
4147             * | | | \ * |
4148             E * E>A | E>B | E>C | \ * E>D |
4149             * | | | \ * |
4150             -----*********************************-------+
4151             | | | | | \ |
4152             D | D>A | D>B | D>C | D>E | \ |
4153             | | | | | \ |
4154             -----+-------+-------+-------+-------+-------+
4155              
4156             Choice D would be sorted in the same
4157             way. Of course the maximum sequence score
4158             would occur when choice D is between choices C
4159             and E, so D is moved there.
4160              
4161             | | | | | |
4162             | A | B | C | D | E |
4163             | | | | | |
4164             -----*****************************************
4165             * \ | | | | *
4166             A * \ | A>B | A>C | A>D | A>E *
4167             * \ | | | | *
4168             -----*-------+-------+-------+-------+-------*
4169             * | \ | | | *
4170             B * B>A | \ | B>C | B>D | B>E *
4171             * | \ | | | *
4172             -----*-------+-------+-------+-------+-------*
4173             * | | \ | | *
4174             C * C>A | C>B | \ | C>D | C>E *
4175             * | | \ | | *
4176             -----*-------+-------+-------+-------+-------*
4177             * | | | \ | *
4178             D * D>A | D>B | D>C | \ | D>E *
4179             * | | | \ | *
4180             -----*-------+-------+-------+-------+-------*
4181             * | | | | \ *
4182             E * E>A | E>B | E>C | E>D | \ *
4183             * | | | | \ *
4184             -----*****************************************
4185              
4186             Now there are no more choices to sort, so
4187             the resulting sequence is A, B, C, D, E.
4188             In this sequence the full sequence score
4189             -- which equals A>B + A>C + A>D +
4190             A>E + B>C + B>D + B>E + C>D +
4191             C>E + D>E -- is likely to be the
4192             highest possible sequence score.
4193              
4194             Additional calculations, as described below,
4195             are needed because in rare cases it is possible
4196             that moving two or more choices at the same
4197             time could produce a higher sequence
4198             score. This concept is analogous to
4199             climbing a mountain in foggy conditions by
4200             always heading in the locally higher direction
4201             and ending up at the top of a peak and then,
4202             when the fog clears, seeing a higher peak.
4203              
4204             Full calculation method for VoteFair popularity ranking:
4205              
4206             This is a description of the full algorithm
4207             used to calculate VoteFair popularity ranking
4208             results.
4209              
4210             The algorithm begins by calculating the
4211             Choice-Specific Pairwise-Score ranking.
4212             This pre-sort is a required part of the
4213             process. Without it, some unusual cases
4214             can cause the calculations to fail to find the
4215             sequence with the highest score. This
4216             pre-sort is analogous to starting a search for
4217             the highest mountain peak within a mountain
4218             range instead of starting the search within a
4219             large valley.
4220              
4221             The next step is to apply the insertion-sort
4222             method as described in the section above,
4223             including starting at the left/highest end.
4224              
4225             To ensure that all possible moves of each
4226             choice are considered, the insertion-sort
4227             method is done in both directions.
4228             Sorting in both directions means that in some
4229             sorting passes sorting moves choices to the
4230             left, as explained in the above example.
4231             In other sorting passes sorting starts by
4232             considering the right-most choice as the first
4233             sorted choice, and choices move to the right,
4234             into the sorted portion. This convention
4235             ensures movement for choices that need to move
4236             right, instead of left, in order to cause an
4237             increase in the score.
4238              
4239             Complications can arise when there is
4240             "circular ambiguity", so additional steps are
4241             used. The most common cases of circular
4242             ambiguity involve several choices that are tied
4243             for the same sort-order position.
4244              
4245             A key part of dealing with circular
4246             ambiguity is to follow this convention:
4247             whenever a choice can produce the same,
4248             highest, sequence score at more than one
4249             position, the choice is moved to the farthest
4250             of those highest-sequence-score positions.
4251              
4252             Another part of dealing with these
4253             complications is to sort the sequence multiple
4254             times.
4255              
4256             During the second sorting pass, if there is
4257             no circular ambiguity, the sequence of the
4258             choices in the pairwise matrix remains the
4259             same. This lack of movement (when there
4260             is no circular ambiguity) occurs because the
4261             sorted and unsorted portions are
4262             adjacent. Specifically, each choice to be
4263             sorted is already at the top (for left-movement
4264             sorting) or bottom (for right-movement sorting)
4265             of the "unsorted" portion, and it is being
4266             moved to the bottom (for left-movement sorting)
4267             or top (for right-movement sorting) of
4268             the "sorted" portion. In such cases
4269             the only thing that moves is the boundary
4270             between the sorted choices and unsorted
4271             choices.
4272              
4273             However, in cases that involve circular
4274             ambiguity, the positions of some choices will
4275             change during the second and later sorting
4276             passes. This happens because the
4277             convention (as explained above) is to move each
4278             choice as far as it will go, within the limits
4279             of maximizing the sequence score.
4280              
4281             During the sorting passes the highest
4282             sort-order (sequence) position of each choice
4283             is tracked, and the lowest sort-order position
4284             of each choice is tracked. These highest
4285             and lowest positions are reset (to current
4286             positions) whenever the sequence score
4287             increases to a higher score. At the end
4288             of the sorting process the highest and lowest
4289             positions reveal which choices are tied at the
4290             same popularity ranking level.
4291              
4292             Using the insertion-sort example, if choices
4293             B, C, and D can be in any order and still
4294             produce the same highest sequence score, then
4295             each of these choices would move to the left of
4296             the other two each time it is sorted, and each
4297             of these choices would have the same
4298             highest-ranked position of second place, and
4299             each would have the same lowest-ranked position
4300             of fourth place. Because these three choices
4301             have the same highest and lowest positions,
4302             they are easily identified as tied (at the same
4303             popularity ranking).
4304              
4305             More complex cases of circular ambiguity can
4306             occur. To deal with these cases, and to
4307             ensure the correctness of the "winner" (the
4308             most popular choice), the sorting process is
4309             repeated for the top half (plus one) of the
4310             highest-ranked choices, and this sub-set
4311             sorting is repeated until there are just three
4312             choices. For example, if there are 12
4313             choices, the sorting process is done for 12
4314             choices, then the top 7 choices, then the top 4
4315             choices, and finally the top 3 choices.
4316             Then the highest-ranked choice (or the choices
4317             that are tied at the top) is kept at the
4318             highest rank while the other choices are sorted
4319             a final time. (If, instead, the
4320             least-popular choice is the most important one
4321             to identify correctly, the data supplied to
4322             this algorithm can be inverted according to
4323             preference levels, and then the calculated
4324             ranking can be reversed.)
4325              
4326             As a clarification, the extra sub-set
4327             sorting is done only if more than one sequence
4328             has the same highest sequence score. This
4329             point is significant if the distinction between
4330             VoteFair popularity ranking and the
4331             Condorcet-Kemeny method is relevant.
4332             Specifically, the Condorcet-Kemeny method does
4333             not indicate how such "tied" sequence scores
4334             should be resolved, whereas VoteFair popularity
4335             ranking resolves such "tied" sequence scores as
4336             part of its calculation process.
4337              
4338             After all the sorting has been done, the
4339             highest and lowest ranking levels are used to
4340             determine the results. For each choice
4341             its highest and lowest ranking levels
4342             are added together (which equals twice their
4343             average) and then multiplied times a
4344             constant. The constant equals 10 times
4345             the number of choices minus one. These
4346             numbers are converted to integers, and then
4347             these "averaged scaled integerized" values are
4348             used as the non-normalized ranking
4349             levels. Two or more choices are ranked at
4350             the same level if they have the same
4351             "averaged-scaled-integerized" ranking
4352             values.
4353              
4354             The final calculation step is to normalize
4355             the "averaged-scaled-integerized" ranking
4356             levels so that the normalized ranking levels
4357             are consecutive, namely 1, 2, 3, etc. (so that
4358             no ranking levels are skipped).
4359              
4360             The result is a ranking that identifies
4361             which choice is first-most popular, which
4362             choice is second-most popular, and so on down
4363             to which choice is least popular. Ties
4364             can occur at any level.
4365              
4366             Calculation time:
4367              
4368             The full algorithm used to calculate
4369             VoteFair popularity ranking results has a
4370             calculation time that is less than or equal to
4371             the following polynomial function:
4372              
4373             T = A + ( B * N ) + ( C * ( N * N ) )
4374              
4375             where T is the calculation time, N is the
4376             number of choices, and A and B and C are
4377             constants. (In mathematical notation, N *
4378             N would be written as N squared.) This
4379             function includes the calculation time required
4380             for the Choice-Specific Pairwise-Score (CSPS)
4381             pre-sort calculations.
4382              
4383             This time contrasts with the slow execution
4384             times of the "NP-hard" approach, in which
4385             every sequence score is calculated in order to
4386             find the sequence with the highest score.
4387             If every sequence score were calculated (from
4388             scratch), the calculation time would be
4389             proportional to:
4390              
4391             N! * N * N
4392              
4393             where N is the number of choices, N! is N
4394             factorial (2 * 3 * 4 * ... * N), and N * N
4395             equals N squared. Note that N factorial
4396             equals the number of possible sequences, and N
4397             squared times one-half approximately equals the
4398             number of pairwise counts that are added to
4399             calculate each sequence score.
4400              
4401             This clarification about calculation time is
4402             included because there is an academically
4403             common -- yet mistaken -- belief that
4404             calculating the "Condorcet-Kemeny method" is
4405             "NP-hard" and cannot be calculated in a time
4406             that is proportional to a polynomial function
4407             of N (the number of choices).
4408              
4409             (c) Copyright 2011 Richard Fobes at VoteFair.org
4410              
4411             (This description copied from VoteFair.org
4412             with permission.)
4413              
4414             =cut
4415              
4416             #-----------------------------------------------
4417             #-----------------------------------------------
4418             # calc_votefair_insertion_sort_popularity_rank
4419             #-----------------------------------------------
4420             #-----------------------------------------------
4421              
4422             sub calc_votefair_insertion_sort_popularity_rank
4423             {
4424              
4425 84     84 1 215 my $adjusted_choice ;
4426             my $adjusted_choice_to_move ;
4427 0         0 my $new_adjusted_choice ;
4428 0         0 my $new_adjusted_choice_count ;
4429 0         0 my $starting_adjusted_choice_number ;
4430 0         0 my $local_adjusted_choice_count ;
4431 0         0 my $tally_adjusted_choice_for_choice_to_move ;
4432 0         0 my $tally_adjusted_choice_for_choice_at_destination ;
4433 0         0 my $actual_choice ;
4434 0         0 my $actual_choice_to_move ;
4435 0         0 my $actual_choice_at_destination ;
4436 0         0 my $count_of_choices_in_top_half ;
4437 0         0 my $number_of_choices_to_shift ;
4438 0         0 my $sequence_position ;
4439 0         0 my $destination_sequence_position ;
4440 0         0 my $source_sequence_position ;
4441 0         0 my $to_position ;
4442 0         0 my $from_position ;
4443 0         0 my $position_of_choice_to_move ;
4444 0         0 my $position_number ;
4445 0         0 my $actual_destination ;
4446 0         0 my $possible_destination ;
4447 0         0 my $maximum_move_distance_allowed ;
4448 0         0 my $direction_increment ;
4449 0         0 my $distance_to_possible_destination ;
4450 0         0 my $number_of_positions_sorted ;
4451 0         0 my $ranking_level ;
4452 0         0 my $special_ranking_level ;
4453 0         0 my $highest_rank ;
4454 0         0 my $lowest_rank ;
4455 0         0 my $choice_counter ;
4456 0         0 my $pair_counter ;
4457 0         0 my $score_increase ;
4458 0         0 my $tally_choice_to_move_over_choice_at_destination ;
4459 0         0 my $tally_choice_at_destination_over_choice_to_move ;
4460 0         0 my $largest_subset_sum ;
4461 0         0 my $final_stage_reached_at_main_loop_count ;
4462 0         0 my $pass_number ;
4463 0         0 my $sort_pass_counter ;
4464 0         0 my $sort_pass_count_at_last_move ;
4465 0         0 my $sort_pass_counter_maximum ;
4466 0         0 my $recent_sort_pass_count_in_direction_left ;
4467 0         0 my $recent_sort_pass_count_in_direction_right ;
4468 0         0 my $pass_count_at_last_score_increase ;
4469 0         0 my $reached_stable_condition_at_pass_count ;
4470 0         0 my $count_of_sequences_with_same_highest_score ;
4471 0         0 my $main_loop_count ;
4472 0         0 my $main_loop_maximum_count ;
4473 0         0 my $scale_value ;
4474 0         0 my $true_or_false_log_details ;
4475 0         0 my $highest_rank_threshold ;
4476 0         0 my $count_of_highest_ranked_choices ;
4477 0         0 my $count_of_lower_ranked_choices ;
4478 0         0 my $adjusted_choice_overall ;
4479 0         0 my $possible_ranking_level ;
4480 0         0 my $actual_first_choice ;
4481 0         0 my $actual_second_choice ;
4482 0         0 my $tally_adjusted_first_choice ;
4483 0         0 my $tally_adjusted_second_choice ;
4484 0         0 my $tally_first_over_second ;
4485 0         0 my $tally_second_over_first ;
4486              
4487 0         0 my @local_actual_choice_for_adjusted_choice ;
4488 0         0 my @actual_choice_at_new_adjusted_choice ;
4489 0         0 my @actual_choice_in_insertion_rank_sequence_position ;
4490 0         0 my @highest_insertion_sort_sequence_position_for_actual_choice ;
4491 0         0 my @lowest_insertion_sort_sequence_position_for_actual_choice ;
4492 0         0 my @pass_number_at_last_rerank_for_adjusted_choice ;
4493 0         0 my @adjusted_choice_count_at_stage ;
4494 0         0 my @highest_ranked_actual_choice_at_count ;
4495 0         0 my @lower_ranked_actual_choice_at_count ;
4496 0         0 my @local_adjusted_choice_for_actual_choice ;
4497              
4498              
4499             #-----------------------------------------------
4500             # Hide or show the details in the log file.
4501             # This choice can slow down the software
4502             # because it creates a large log file.
4503              
4504 84         120 $true_or_false_log_details = $global_false ;
4505 84         136 $true_or_false_log_details = $global_true ;
4506 84 50       190 if ( $global_logging_info == $global_true )
4507             {
4508 84         141 print LOGOUT "[insertion sort, beginning calc_votefair_insertion_sort_popularity_rank subroutine]\n\n" ;
4509 84 50       178 if ( $true_or_false_log_details == $global_true )
4510             {
4511 84         305 print LOGOUT "[insertion sort, details shown (change flag value to hide details)]\n" ;
4512             } else
4513             {
4514 0         0 print LOGOUT "[insertion sort, details hidden (change flag value to view details)]\n" ;
4515             }
4516             }
4517              
4518              
4519             #-----------------------------------------------
4520             # Set the results to zero in case an error is
4521             # encountered.
4522              
4523 84         223 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
4524             {
4525 475         523 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
4526 475         613 $global_insertion_sort_popularity_rank_for_actual_choice[ $actual_choice ] = 0 ;
4527 475         1070 $pass_number_at_last_rerank_for_adjusted_choice[ $adjusted_choice ] = 0 ;
4528             }
4529              
4530              
4531             #-----------------------------------------------
4532             # If there are not at least two choices,
4533             # indicate an error.
4534              
4535 84 50       241 if ( $global_adjusted_choice_count < 2 )
4536             {
4537 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, ERROR: number of (adjusted) choices is less than two]\n" } ;
  0         0  
4538 0         0 return ;
4539             }
4540              
4541              
4542             #-----------------------------------------------
4543             # If the total vote count is zero, indicate an
4544             # error.
4545              
4546 84 50       221 if ( $global_current_total_vote_count < 1 )
4547             {
4548 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, ERROR: number of votes is zero]\n" } ;
  0         0  
4549 0         0 return ;
4550             }
4551              
4552              
4553             #-----------------------------------------------
4554             # Initialize the choice sequence. Use the
4555             # sequence calculated by the choice-specific
4556             # score-based ranking calculations.
4557             #
4558             # In case there are no results from those calculations,
4559             # initialize the sequence to be in numeric
4560             # order (choice 1, choice 2, etc.).
4561             # However, in complex cases, numeric order
4562             # may produce the wrong results!
4563              
4564 84         225 for ( $sequence_position = 1 ; $sequence_position <= $global_adjusted_choice_count ; $sequence_position ++ )
4565             {
4566 475         527 $adjusted_choice = $sequence_position ;
4567 475         519 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
4568 475         1093 $actual_choice_in_insertion_rank_sequence_position[ $sequence_position ] = $actual_choice ;
4569             }
4570 84         125 $adjusted_choice = 1 ;
4571 84         123 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
4572 84 50 33     405 if ( ( defined( $global_choice_score_popularity_rank_for_actual_choice[ $actual_choice ] ) ) && ( $global_choice_score_popularity_rank_for_actual_choice[ $actual_choice ] > 0 ) )
4573             {
4574 84         156 $sequence_position = 1 ;
4575 84         245 for ( $ranking_level = 1 ; $ranking_level <= $global_adjusted_choice_count ; $ranking_level ++ )
4576             {
4577 475         1006 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
4578             {
4579 2964         4985 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
4580 2964 100       8413 if ( $global_choice_score_popularity_rank_for_actual_choice[ $actual_choice ] == $ranking_level )
4581             {
4582 475         579 $actual_choice_in_insertion_rank_sequence_position[ $sequence_position ] = $actual_choice ;
4583 475 50       876 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, put choice " . $actual_choice . " into sequence position " . $sequence_position . "]\n" } ;
  475         1282  
4584 475         562 $sequence_position ++ ;
4585 475 100       1555 if ( $sequence_position > $global_adjusted_choice_count )
4586             {
4587 84         270 last ;
4588             }
4589             }
4590             }
4591             }
4592             } else
4593             {
4594 0         0 $global_output_warning_messages_case_or_question_specific .= $global_question_specific_warning_begin . " triggered-program-bug" . "\n-----\n\n" ;
4595 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[ERROR: the results of the choice-specific score-based calculations are not available, so the results might not be correct!]\n" } ;
  0         0  
4596             }
4597              
4598              
4599             #-----------------------------------------------
4600             # For debugging, display the tally numbers in
4601             # an array/matrix arrangement.
4602              
4603 84 50       194 if ( $true_or_false_log_details == $global_true )
4604             {
4605 84         210 for ( $sequence_position = 1 ; $sequence_position <= $global_adjusted_choice_count ; $sequence_position ++ )
4606             {
4607 475         553 $actual_choice = $actual_choice_in_insertion_rank_sequence_position[ $sequence_position ] ;
4608 475         983 $global_log_info_choice_at_position[ $sequence_position ] = $actual_choice ;
4609             }
4610 84         176 print LOGOUT "[insertion sort, initial ranking:]\n" ;
4611 84         161 &internal_view_matrix( ) ;
4612             }
4613              
4614              
4615             #-----------------------------------------------
4616             # Use a local value for the adjusted choice
4617             # count. This allows the count to change.
4618              
4619 84         128 $local_adjusted_choice_count = $global_adjusted_choice_count ;
4620              
4621              
4622             #-----------------------------------------------
4623             # Create lists that associate adjusted choice
4624             # numbers with actual choice numbers, in both
4625             # directions. These local values are used
4626             # instead of the global values because these
4627             # adjusted choice numbers will change.
4628              
4629 84         226 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
4630             {
4631 475         525 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
4632 475         550 $local_actual_choice_for_adjusted_choice[ $adjusted_choice ] = $actual_choice ;
4633 475         1071 $local_adjusted_choice_for_actual_choice[ $actual_choice ] = $adjusted_choice ;
4634             }
4635              
4636              
4637             #-----------------------------------------------
4638             # Begin a loop that repeats in order to handle
4639             # the different stages in the calculations,
4640             # where the different stages sort either all
4641             # the choices or a subset of the choices.
4642             # This loop does not exit here; it exits when
4643             # the stages are all done.
4644             # Note that this loop is only repeated if
4645             # more than one sequence has the same highest
4646             # sequence score.
4647              
4648 84         110 $global_sequence_score_using_insertion_sort_method = 0 ;
4649 84         105 $count_of_sequences_with_same_highest_score = 0 ;
4650 84         110 $final_stage_reached_at_main_loop_count = 0 ;
4651 84         118 $main_loop_maximum_count = 10 ;
4652 84         251 for ( $main_loop_count = 1 ; $main_loop_count <= $main_loop_maximum_count ; $main_loop_count ++ )
4653             {
4654 252 50       543 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in main loop, main-loop number is " . $main_loop_count . "]\n" } ;
  252         677  
4655              
4656              
4657             #-----------------------------------------------
4658             # If this is the "starting" stage, sort all the
4659             # choices (starting with the sort order
4660             # calculated by the choice-specific score-based
4661             # method).
4662              
4663 252 100       575 if ( $main_loop_count == 1 )
4664             {
4665 84 50       192 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in main loop, first/start stage, so sorting all choices]\n\n" } ;
  84         150  
4666             }
4667              
4668              
4669             #-----------------------------------------------
4670             # If the final stage is complete, exit the loop.
4671              
4672 252 50 33     675 if ( ( $final_stage_reached_at_main_loop_count > 0 ) && ( $main_loop_count >= $final_stage_reached_at_main_loop_count ) )
4673             {
4674 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in main loop, final stage done, so exiting main loop]\n\n" } ;
  0         0  
4675 0         0 last ;
4676             }
4677              
4678              
4679             #-----------------------------------------------
4680             # If at least one pass of sorting has been done
4681             # and the total number of choices is 2, the
4682             # sorting is done, so exit the main loop.
4683              
4684 252 100 100     1195 if ( ( $main_loop_count > 1 ) && ( $global_adjusted_choice_count <= 2 ) )
4685             {
4686 7 50       19 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in main loop, choice count is just one or two, sorting is done, so exiting main loop]\n" } ;
  7         11  
4687 7         13 last ;
4688             }
4689              
4690              
4691             #-----------------------------------------------
4692             # If this is not the starting stage, and is not
4693             # the final stage (checked above), and at least
4694             # one pass of sub-sorting has been done, and
4695             # the number of sub-sorted choices is now 3 or
4696             # less, request starting the final stage.
4697              
4698 245 100 100     1090 if ( ( $main_loop_count > 1 ) && ( $local_adjusted_choice_count <= 3 ) && ( $local_adjusted_choice_count < $global_adjusted_choice_count ) )
      100        
4699             {
4700 44         67 $final_stage_reached_at_main_loop_count = $main_loop_count ;
4701 44 50       135 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in main loop, count of choices just sub-sorted (" . $local_adjusted_choice_count . ") is three or less, so starting final stage]\n" } ;
  44         107  
4702             }
4703              
4704              
4705             #-----------------------------------------------
4706             # If this is not the starting stage, and is not the
4707             # final stage, attempt to reduce the number
4708             # of choices being sorted. Identify the choices
4709             # in the top half, plus the next-ranked choice.
4710             # If appropriate, these choices will be sub-sorted.
4711              
4712 245 100 100     1173 if ( ( $main_loop_count > 1 ) && ( $local_adjusted_choice_count > 3 ) )
4713             {
4714 99         234 $new_adjusted_choice_count = int( ( $local_adjusted_choice_count / 2 ) + 1 ) ;
4715 99 50       338 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in main loop, finding " . $new_adjusted_choice_count . " choices at highest rankings]\n" } ;
  99         546  
4716 99         657 for ( $adjusted_choice = 1 ; $adjusted_choice <= $local_adjusted_choice_count ; $adjusted_choice ++ )
4717             {
4718 572         624 $actual_choice = $local_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
4719 572         1372 $actual_choice_at_new_adjusted_choice[ $adjusted_choice ] = 0 ;
4720             }
4721 99         167 $count_of_choices_in_top_half = 0 ;
4722 99         247 for ( $highest_rank_threshold = 1 ; $highest_rank_threshold <= $local_adjusted_choice_count ; $highest_rank_threshold ++ )
4723             {
4724 339         713 for ( $adjusted_choice = 1 ; $adjusted_choice <= $local_adjusted_choice_count ; $adjusted_choice ++ )
4725             {
4726 2118         2243 $actual_choice = $local_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
4727 2118         2292 $highest_rank = $highest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice ] ;
4728 2118 100       5539 if ( $highest_rank == $highest_rank_threshold )
4729             {
4730 388         371 $count_of_choices_in_top_half ++ ;
4731 388         397 $new_adjusted_choice = $count_of_choices_in_top_half ;
4732 388         543 $actual_choice_at_new_adjusted_choice[ $new_adjusted_choice ] = $actual_choice ;
4733 388 50       690 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[ choice " . $actual_choice . " (at ranking level " . $highest_rank . ") will be sub-sorted as adjusted choice " . $new_adjusted_choice . "]\n" } ;
  388         1633  
4734             }
4735             }
4736 339 100       896 if ( $count_of_choices_in_top_half >= $new_adjusted_choice_count )
4737             {
4738 99         124 last ;
4739             }
4740             }
4741 99 50       195 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in main loop, found " . $count_of_choices_in_top_half . " choices at highest rankings]\n" } ;
  99         286  
4742              
4743              
4744             #-----------------------------------------------
4745             # If the just-calculated number of choices to be
4746             # sub-sorted is less than three, or has not
4747             # changed (been reduced), request starting the final
4748             # stage (which will sort all the choices except
4749             # the highest-ranked choice).
4750              
4751 99 50       290 if ( $count_of_choices_in_top_half < 3 )
    100          
4752             {
4753 0         0 $final_stage_reached_at_main_loop_count = $main_loop_count ;
4754 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in main loop, count of choices to sub-sort (" . $local_adjusted_choice_count . ") is less than three, so starting final stage]\n" } ;
  0         0  
4755             } elsif ( $count_of_choices_in_top_half == $local_adjusted_choice_count )
4756             {
4757 11         24 $final_stage_reached_at_main_loop_count = $main_loop_count ;
4758 11 50       35 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in main loop, count of choices to sub-sort (" . $local_adjusted_choice_count . ") did not change (which would cause an endless loop), so starting final stage]\n" } ;
  11         28  
4759              
4760              
4761             #-----------------------------------------------
4762             # If the number of choices to be sub-sorted is
4763             # less than the previous number of choices
4764             # sorted, but is not less than three, prepare to sort them
4765             # by shifting the specified number of top-ranked
4766             # choices into the lowest-numbered sequence
4767             # positions.
4768              
4769             } else
4770             {
4771 88         121 $local_adjusted_choice_count = $count_of_choices_in_top_half ;
4772 88         226 $adjusted_choice_count_at_stage[ $main_loop_count ] = $local_adjusted_choice_count ;
4773 88 50       195 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in main loop, now adjusted choice count is " . $local_adjusted_choice_count . "]\n" } ;
  88         184  
4774 88         226 for ( $adjusted_choice = 1 ; $adjusted_choice <= $local_adjusted_choice_count ; $adjusted_choice ++ )
4775             {
4776 341         394 $actual_choice = $actual_choice_at_new_adjusted_choice[ $adjusted_choice ] ;
4777 341         375 $local_adjusted_choice_for_actual_choice[ $actual_choice ] = $adjusted_choice ;
4778 341         406 $local_actual_choice_for_adjusted_choice[ $adjusted_choice ] = $actual_choice ;
4779 341         365 $sequence_position = $adjusted_choice ;
4780 341         763 $actual_choice_in_insertion_rank_sequence_position[ $sequence_position ] = $actual_choice ;
4781             }
4782             }
4783             }
4784              
4785              
4786             #-----------------------------------------------
4787             # If this is the final stage, identify the
4788             # highest-ranked choices -- based on having
4789             # been at the highest sequence position (during
4790             # the most recent sorting pass) -- and save
4791             # them separately. Also create a list of the
4792             # other choices.
4793              
4794 245 100       544 if ( $final_stage_reached_at_main_loop_count == $main_loop_count )
4795             {
4796 55 50       126 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in main loop, starting final stage]\n" } ;
  55         101  
4797 55         92 $count_of_highest_ranked_choices = 0 ;
4798 55         71 $count_of_lower_ranked_choices = 0 ;
4799 55         159 for ( $adjusted_choice = 1 ; $adjusted_choice <= $local_adjusted_choice_count ; $adjusted_choice ++ )
4800             {
4801 179         210 $actual_choice = $local_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
4802 179 100       319 if ( $highest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice ] == 1 )
4803             {
4804 67         108 $count_of_highest_ranked_choices ++ ;
4805 67         122 $highest_ranked_actual_choice_at_count[ $count_of_highest_ranked_choices ] = $actual_choice ;
4806 67 50       168 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in main loop, choice " . $actual_choice . " is at highest rank]\n" } ;
  67         296  
4807             } else
4808             {
4809 112         113 $count_of_lower_ranked_choices ++ ;
4810 112         158 $lower_ranked_actual_choice_at_count[ $count_of_lower_ranked_choices ] = $actual_choice ;
4811 112         171 $highest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice ] = $global_adjusted_choice_count ;
4812 112         160 $lowest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice ] = $global_adjusted_choice_count ;
4813 112 50       225 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in main loop, choice " . $actual_choice . " is at lower rank]\n" } ;
  112         408  
4814             }
4815             }
4816              
4817              
4818             #-----------------------------------------------
4819             # If all the choices are tied at the highest
4820             # level, indicate this situation and exit the
4821             # main loop.
4822              
4823 55 50       134 if ( $count_of_highest_ranked_choices == $global_adjusted_choice_count )
4824             {
4825 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in main loop, all the choices are tied at the highest level]\n" } ;
  0         0  
4826 0         0 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
4827             {
4828 0         0 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
4829 0         0 $highest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice ] = 1 ;
4830 0         0 $lowest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice ] = 1 ;
4831 0         0 $sequence_position = $actual_choice ;
4832 0         0 $actual_choice_in_insertion_rank_sequence_position[ $sequence_position ] = $actual_choice ;
4833 0         0 $local_actual_choice_for_adjusted_choice[ $adjusted_choice ] = $actual_choice ;
4834 0         0 $local_adjusted_choice_for_actual_choice[ $actual_choice ] = $adjusted_choice ;
4835             }
4836 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in main loop, exiting main loop]\n" } ;
  0         0  
4837 0         0 last ;
4838             }
4839              
4840              
4841             #-----------------------------------------------
4842             # If this is the final stage, put all the choices
4843             # that are not at the highest rank into a sequence
4844             # for final sorting. Use the sequence calculated
4845             # by VoteFair choice-specific score-based ranking.
4846              
4847 55 50       134 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in main loop, preparing to sub-sort the choices that are not highest ranked]\n" } ;
  55         151  
4848 55         73 $local_adjusted_choice_count = $global_adjusted_choice_count - $count_of_highest_ranked_choices ;
4849 55         73 $new_adjusted_choice = 1 ;
4850 55         190 for ( $adjusted_choice_overall = 1 ; $adjusted_choice_overall <= $global_adjusted_choice_count ; $adjusted_choice_overall ++ )
4851             {
4852 363         398 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice_overall ] ;
4853 363 100       793 if ( $highest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice ] > 1 )
4854             {
4855 296         327 $local_adjusted_choice_for_actual_choice[ $actual_choice ] = $new_adjusted_choice ;
4856 296         312 $local_actual_choice_for_adjusted_choice[ $new_adjusted_choice ] = $actual_choice ;
4857 296         612 $new_adjusted_choice ++ ;
4858             }
4859             }
4860 55         104 $sequence_position = 1 ;
4861 55         173 for ( $possible_ranking_level = 1 ; $possible_ranking_level <= $global_adjusted_choice_count ; $possible_ranking_level ++ )
4862             {
4863 363         726 for ( $adjusted_choice = 1 ; $adjusted_choice <= $local_adjusted_choice_count ; $adjusted_choice ++ )
4864             {
4865 2207         2335 $actual_choice = $local_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
4866 2207 100       6546 if ( $possible_ranking_level == $global_choice_score_popularity_rank_for_actual_choice[ $actual_choice ] )
4867             {
4868 296         335 $actual_choice_in_insertion_rank_sequence_position[ $sequence_position ] = $actual_choice ;
4869 296 50       598 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[ choice " . $actual_choice . " is at sequence position " . $sequence_position . " and is now adjusted choice " . $adjusted_choice . "]\n" } ;
  296         757  
4870 296         730 $sequence_position ++ ;
4871             }
4872             }
4873             }
4874 55 50       144 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in main loop, will sort all other choices]\n" } ;
  55         105  
4875             }
4876              
4877              
4878             #-----------------------------------------------
4879             # Initialize the values that keep track of
4880             # each choice's highest and lowest positions.
4881              
4882 245         633 for ( $sequence_position = 1 ; $sequence_position <= $local_adjusted_choice_count ; $sequence_position ++ )
4883             {
4884 1166         1410 $actual_choice = $actual_choice_in_insertion_rank_sequence_position[ $sequence_position ] ;
4885 1166         1302 $adjusted_choice = $local_adjusted_choice_for_actual_choice[ $actual_choice ] ;
4886 1166         1354 $highest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice ] = $sequence_position ;
4887 1166         1419 $lowest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice ] = $sequence_position ;
4888 1166 50       2099 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in main loop, next in sequence is choice " . $actual_choice . "]\n" } ;
  1166         4235  
4889             }
4890              
4891              
4892             #-----------------------------------------------
4893             # Log the starting sequence.
4894              
4895 245 50       470 if ( $true_or_false_log_details == $global_true )
4896             {
4897 245         520 print LOGOUT "\n[insertion sort, in sort-pass loop, starting sequence is: " ;
4898 245         536 for ( $sequence_position = 1 ; $sequence_position <= $local_adjusted_choice_count ; $sequence_position ++ )
4899             {
4900 1166         1380 $actual_choice = $actual_choice_in_insertion_rank_sequence_position[ $sequence_position ] ;
4901 1166         2902 print LOGOUT $actual_choice . " , " ;
4902             }
4903 245         393 print LOGOUT "]\n" ;
4904             }
4905              
4906              
4907             #-----------------------------------------------
4908             # Initialize values that are used in the
4909             # upcoming loop that repeatedly sorts the
4910             # choices.
4911              
4912 245         295 $direction_increment = 1 ;
4913 245         309 $starting_adjusted_choice_number = 1 ;
4914 245         257 $sort_pass_count_at_last_move = 0 ;
4915 245         265 $sort_pass_counter_maximum = 10 ;
4916 245         278 $pass_count_at_last_score_increase = 0 ;
4917 245         293 $recent_sort_pass_count_in_direction_left = 0 ;
4918 245         255 $recent_sort_pass_count_in_direction_right = 0 ;
4919 245         279 $reached_stable_condition_at_pass_count = 0 ;
4920              
4921              
4922             #-----------------------------------------------
4923             # Begin a loop that repeatedly sorts the
4924             # choices. Normally the loop does not reach
4925             # the maximum loop count used here.
4926              
4927 245         620 for ( $sort_pass_counter = 1 ; $sort_pass_counter <= $sort_pass_counter_maximum ; $sort_pass_counter ++ )
4928             {
4929 1391 50       2532 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in sort-pass loop, sort pass counter = " . $sort_pass_counter . ", last left sort count is " . $recent_sort_pass_count_in_direction_left . ", last right sort count = " . $recent_sort_pass_count_in_direction_right . "]\n" } ;
  1391         4394  
4930              
4931              
4932             #-----------------------------------------------
4933             # If there is just one choice, indicate its
4934             # sort order, and exit the sort-pass loop.
4935              
4936 1391 50       2876 if ( $local_adjusted_choice_count == 1 )
4937             {
4938 0         0 $actual_choice = $actual_choice_in_insertion_rank_sequence_position[ 1 ] ;
4939 0         0 $highest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice ] = 1 ;
4940 0         0 $lowest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice ] = 1 ;
4941 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in sort-pass loop, only one choice, so no need to sort it]\n" } ;
  0         0  
4942 0         0 last ;
4943             }
4944              
4945              
4946             #-----------------------------------------------
4947             # If there are just two choices, just look at
4948             # the two relevant pairwise-count numbers,
4949             # sort the two choices accordingly, and then
4950             # exit the sort-pass loop.
4951              
4952 1391 100       2691 if ( $local_adjusted_choice_count == 2 )
4953             {
4954 12         21 $actual_first_choice = $actual_choice_in_insertion_rank_sequence_position[ 1 ] ;
4955 12         17 $actual_second_choice = $actual_choice_in_insertion_rank_sequence_position[ 2 ] ;
4956 12 50       29 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in sort-pass loop, only two choices, " . $actual_second_choice . " and " . $actual_first_choice . "]\n" } ;
  12         63  
4957 12         14 $tally_adjusted_first_choice = $global_adjusted_choice_for_actual_choice[ $actual_first_choice ] ;
4958 12         19 $tally_adjusted_second_choice = $global_adjusted_choice_for_actual_choice[ $actual_second_choice ] ;
4959 12 100       30 if ( $tally_adjusted_first_choice < $tally_adjusted_second_choice )
4960             {
4961 8         13 $pair_counter = $global_pair_counter_offset_for_first_adjusted_choice[ $tally_adjusted_first_choice ] + $tally_adjusted_second_choice ;
4962 8         13 $tally_first_over_second = $global_tally_first_over_second_in_pair[ $pair_counter ] ;
4963 8         15 $tally_second_over_first = $global_tally_second_over_first_in_pair[ $pair_counter ] ;
4964             } else
4965             {
4966 4         6 $pair_counter = $global_pair_counter_offset_for_first_adjusted_choice[ $tally_adjusted_second_choice ] + $tally_adjusted_first_choice ;
4967 4         5 $tally_first_over_second = $global_tally_second_over_first_in_pair[ $pair_counter ] ;
4968 4         8 $tally_second_over_first = $global_tally_first_over_second_in_pair[ $pair_counter ] ;
4969             }
4970 12 100       43 if ( $tally_first_over_second == $tally_second_over_first )
    50          
4971             {
4972 2         4 $highest_insertion_sort_sequence_position_for_actual_choice[ $actual_first_choice ] = 1 ;
4973 2         4 $lowest_insertion_sort_sequence_position_for_actual_choice[ $actual_first_choice ] = 1 ;
4974 2         3 $highest_insertion_sort_sequence_position_for_actual_choice[ $actual_second_choice ] = 1 ;
4975 2         4 $lowest_insertion_sort_sequence_position_for_actual_choice[ $actual_second_choice ] = 1 ;
4976 2         4 $actual_choice_in_insertion_rank_sequence_position[ 1 ] = $actual_first_choice ;
4977 2         4 $actual_choice_in_insertion_rank_sequence_position[ 2 ] = $actual_second_choice ;
4978 2 50       8 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in sort-pass loop, choice " . $actual_first_choice . " and choice " . $actual_second_choice . " are tied as highest-ranked]\n" } ;
  2         9  
4979             } elsif ( $tally_first_over_second > $tally_second_over_first )
4980             {
4981 10         15 $highest_insertion_sort_sequence_position_for_actual_choice[ $actual_first_choice ] = 1 ;
4982 10         12 $lowest_insertion_sort_sequence_position_for_actual_choice[ $actual_first_choice ] = 1 ;
4983 10         15 $highest_insertion_sort_sequence_position_for_actual_choice[ $actual_second_choice ] = 2 ;
4984 10         18 $lowest_insertion_sort_sequence_position_for_actual_choice[ $actual_second_choice ] = 2 ;
4985 10         17 $actual_choice_in_insertion_rank_sequence_position[ 1 ] = $actual_first_choice ;
4986 10         16 $actual_choice_in_insertion_rank_sequence_position[ 2 ] = $actual_second_choice ;
4987 10 50       29 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in sort-pass loop, choice " . $actual_first_choice . " is ranked higher than choice " . $actual_second_choice . "]\n" } ;
  10         29  
4988             } else
4989             {
4990 0         0 $highest_insertion_sort_sequence_position_for_actual_choice[ $actual_first_choice ] = 2 ;
4991 0         0 $lowest_insertion_sort_sequence_position_for_actual_choice[ $actual_first_choice ] = 2 ;
4992 0         0 $highest_insertion_sort_sequence_position_for_actual_choice[ $actual_second_choice ] = 1 ;
4993 0         0 $lowest_insertion_sort_sequence_position_for_actual_choice[ $actual_second_choice ] = 1 ;
4994 0         0 $actual_choice_in_insertion_rank_sequence_position[ 1 ] = $actual_second_choice ;
4995 0         0 $actual_choice_in_insertion_rank_sequence_position[ 2 ] = $actual_first_choice ;
4996 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in sort-pass loop, choice " . $actual_second_choice . " is ranked higher than choice " . $actual_first_choice . "]\n" } ;
  0         0  
4997             }
4998 12 50       24 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in sort-pass loop, only two choices, they are now sorted]\n" } ;
  12         20  
4999 12         21 last ;
5000             }
5001              
5002              
5003             #-----------------------------------------------
5004             # Exit the sorting process when there have
5005             # been at least two sorting passes (one each
5006             # direction) during which the total score has
5007             # not increased, and then after two more
5008             # passes to ensure the choices have all moved
5009             # as far as possible in each direction.
5010             # The "extra" sorting passes
5011             # ensure that cycles ("ties") have had a
5012             # chance to move the involved ("tied")
5013             # choices to their highest and lowest
5014             # position values.
5015             # Also, when the sorted sequence is stable,
5016             # set a counter that is used to determine
5017             # if more than one sequence has the same
5018             # highest sequence score.
5019              
5020 1379 100 100     5271 if ( ( $sort_pass_counter >= $reached_stable_condition_at_pass_count + 2 ) && ( $reached_stable_condition_at_pass_count > 0 ) )
5021             {
5022 233 50       518 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in sort-pass loop, two extra sorting passes have been done (after stable condition reached), so exiting sorting process]\n\n" } ;
  233         469  
5023 233         377 last ;
5024             }
5025 1146 100 100     8929 if ( ( $sort_pass_counter > $pass_count_at_last_score_increase + 1 ) && ( $recent_sort_pass_count_in_direction_left > $pass_count_at_last_score_increase ) && ( $recent_sort_pass_count_in_direction_right > $pass_count_at_last_score_increase ) && ( $recent_sort_pass_count_in_direction_left > 0 ) && ( $recent_sort_pass_count_in_direction_right > 0 ) && ( $reached_stable_condition_at_pass_count <= 0 ) )
      100        
      66        
      66        
      66        
5026             {
5027 233         294 $reached_stable_condition_at_pass_count = $sort_pass_counter ;
5028 233         245 $count_of_sequences_with_same_highest_score = 1 ;
5029 233 50       441 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in sort-pass loop, sorting has been done in both directions since the last score increase, so indicating stable condition, so will do two more sorting passes]\n" } ;
  233         452  
5030             }
5031              
5032              
5033             #-----------------------------------------------
5034             # Change the sorting direction for different
5035             # sorting passes. When the direction_increment
5036             # value is positive one, the sorting starts at
5037             # the highest-ranked (left) end and moves
5038             # choices left (to the higher-ranked positions).
5039             # When the direction_increment value is
5040             # negative one, sorting starts at the
5041             # lowest-ranked (right) end and moves choices
5042             # to the right (to the lower-ranked positions).
5043             # This symmetry ensures that tied choices pass
5044             # through the same highest and lowest rank
5045             # positions, and that each choice can move to
5046             # every possible position.
5047              
5048 1146 100 100     4221 if ( $sort_pass_counter == 1 )
    100          
    100          
    100          
5049             {
5050 233         282 $direction_increment = 1 ;
5051             } elsif ( $sort_pass_counter == $reached_stable_condition_at_pass_count )
5052             {
5053 233         284 $direction_increment = $direction_increment * -1 ;
5054             } elsif ( $sort_pass_counter == $reached_stable_condition_at_pass_count + 1 )
5055             {
5056 233         321 $direction_increment = $direction_increment * -1 ;
5057             } elsif ( ( $sort_pass_counter == $sort_pass_count_at_last_move + 1 ) && ( $sort_pass_counter == $pass_count_at_last_score_increase + 2 ) )
5058             {
5059 165         174 $direction_increment = $direction_increment ;
5060 165 50       342 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in sort-pass loop, keeping sort direction the same -- because last move was during pass count " . $sort_pass_count_at_last_move . " and last score increase was during pass count " . $pass_count_at_last_score_increase . "]\n\n" } ;
  165         495  
5061             } else
5062             {
5063 282         366 $direction_increment = $direction_increment * -1 ;
5064 282 50       578 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in sort-pass loop, changing to opposite sort direction]\n\n" } ;
  282         724  
5065             }
5066 1146 100       1766 if ( $direction_increment == 1 )
5067             {
5068 639 50       1300 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in sort-pass loop, movement direction is left]\n\n" } ;
  639         1446  
5069             } else
5070             {
5071 507 50       996 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in sort-pass loop, movement direction is right]\n\n" } ;
  507         909  
5072             }
5073              
5074              
5075             #-----------------------------------------------
5076             # For each sorting direction, save the sorting
5077             # pass number for the most recent sorting done
5078             # in that direction.
5079              
5080 1146 100       1723 if ( $direction_increment == 1 )
5081             {
5082 639         802 $recent_sort_pass_count_in_direction_left = $sort_pass_counter ;
5083             } else
5084             {
5085 507         604 $recent_sort_pass_count_in_direction_right = $sort_pass_counter ;
5086             }
5087              
5088              
5089             #-----------------------------------------------
5090             # Begin a loop that moves each unsorted choice
5091             # into the sorted segment.
5092             # Start by regarding the choice in the
5093             # highest-ranked (left-most) sequence position
5094             # as being the first item in the sorted list.
5095             # The "number_of_positions_sorted" value
5096             # counts how many of the first (left-most)
5097             # sequence positions have been sorted, so this
5098             # number separates the sequence into a sorted
5099             # list on the left and an unsorted list on
5100             # the right.
5101              
5102 1146         2375 for ( $number_of_positions_sorted = 1 ; $number_of_positions_sorted < $local_adjusted_choice_count ; $number_of_positions_sorted ++ )
5103             {
5104 4654 50       8448 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in sort-pass loop, number of positions sorted is " . $number_of_positions_sorted . "]\n" } ;
  4654         9820  
5105              
5106              
5107             #-----------------------------------------------
5108             # Identify which choice will be moved from the
5109             # unsorted portion of the list into the sorted
5110             # portion.
5111              
5112 4654 100       7750 if ( $direction_increment == 1 )
5113             {
5114 2561         3118 $position_of_choice_to_move = $number_of_positions_sorted + 1 ;
5115             } else
5116             {
5117 2093         2583 $position_of_choice_to_move = $local_adjusted_choice_count - $number_of_positions_sorted ;
5118             }
5119 4654         5540 $actual_choice_to_move = $actual_choice_in_insertion_rank_sequence_position[ $position_of_choice_to_move ] ;
5120 4654         4896 $adjusted_choice_to_move = $local_adjusted_choice_for_actual_choice[ $actual_choice_to_move ] ;
5121 4654 50       9127 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "\n" } ;
  4654         6185  
5122 4654 50       8706 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in sort-pass loop, check if need to move choice " . $actual_choice_to_move . "]\n" } ;
  4654         10194  
5123              
5124              
5125             #-----------------------------------------------
5126             # If this choice has already traveled to the
5127             # farthest position in this direction, skip
5128             # this choice.
5129              
5130 4654 100       7151 if ( $direction_increment == 1 )
5131             {
5132 2561 100       5714 if ( $highest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice_to_move ] == 1 )
5133             {
5134 125 50       240 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in sort-pass loop, choice " . $adjusted_choice_to_move . " has already been to the highest ranking]\n" } ;
  125         254  
5135 125         312 next ;
5136             }
5137             } else
5138             {
5139 2093 100       4751 if ( $lowest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice_to_move ] == $local_adjusted_choice_count )
5140             {
5141 236 50       628 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in sort-pass loop, choice " . $adjusted_choice_to_move . " has already been to the lowest ranking]\n" } ;
  236         678  
5142 236         615 next ;
5143             }
5144             }
5145              
5146              
5147             #-----------------------------------------------
5148             # Begin a loop that checks each sorted
5149             # position as a possible destination for the
5150             # unsorted choice being moved.
5151              
5152 4293         4852 $maximum_move_distance_allowed = $number_of_positions_sorted ;
5153 4293         4142 $actual_destination = $position_of_choice_to_move ;
5154 4293         4404 $score_increase = 0 ;
5155 4293         4927 $largest_subset_sum = -99999 ;
5156 4293         8614 for ( $distance_to_possible_destination = 1 ; $distance_to_possible_destination <= $maximum_move_distance_allowed ; $distance_to_possible_destination ++ )
5157             {
5158 13822 100       20879 if ( $direction_increment == 1 )
5159             {
5160 7610         9171 $possible_destination = $position_of_choice_to_move - $distance_to_possible_destination ;
5161             } else
5162             {
5163 6212         7145 $possible_destination = $position_of_choice_to_move + $distance_to_possible_destination ;
5164             }
5165 13822         15879 $actual_choice_at_destination = $actual_choice_in_insertion_rank_sequence_position[ $possible_destination ] ;
5166 13822 50       24509 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in sort-pass loop, possible destination to far side of choice " . $actual_choice_at_destination . "]" } ;
  13822         31754  
5167              
5168              
5169             #-----------------------------------------------
5170             # Calculate the increase -- or decrease if
5171             # negative -- in the sequence score that
5172             # would occur if the unsorted choice was to be
5173             # moved to the specified destination (within
5174             # the sorted portion). The subset sums already
5175             # include the tally counts that apply to any
5176             # already-checked positions between the moved
5177             # choice and the target choice.
5178             # This approach speeds up the calculation
5179             # time compared to fully calculating each
5180             # sequence score from scratch.
5181              
5182 13822         15888 $tally_adjusted_choice_for_choice_to_move = $global_adjusted_choice_for_actual_choice[ $actual_choice_to_move ] ;
5183 13822         14351 $tally_adjusted_choice_for_choice_at_destination = $global_adjusted_choice_for_actual_choice[ $actual_choice_at_destination ] ;
5184 13822 50       26768 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[tally choice numbers: " . $actual_choice_to_move . " (" . $tally_adjusted_choice_for_choice_to_move . ") --> " . $actual_choice_at_destination . " (" . $tally_adjusted_choice_for_choice_at_destination . ")]" } ;
  13822         35030  
5185 13822 100       22600 if ( $tally_adjusted_choice_for_choice_to_move < $tally_adjusted_choice_for_choice_at_destination )
5186             {
5187 6783         8053 $pair_counter = $global_pair_counter_offset_for_first_adjusted_choice[ $tally_adjusted_choice_for_choice_to_move ] + $tally_adjusted_choice_for_choice_at_destination ;
5188 6783 100       11036 if ( $direction_increment == 1 )
5189             {
5190 3900         4604 $tally_choice_to_move_over_choice_at_destination = $global_tally_first_over_second_in_pair[ $pair_counter ] ;
5191 3900         5375 $tally_choice_at_destination_over_choice_to_move = $global_tally_second_over_first_in_pair[ $pair_counter ] ;
5192             } else
5193             {
5194 2883         3573 $tally_choice_to_move_over_choice_at_destination = $global_tally_second_over_first_in_pair[ $pair_counter ] ;
5195 2883         3969 $tally_choice_at_destination_over_choice_to_move = $global_tally_first_over_second_in_pair[ $pair_counter ] ;
5196             }
5197             } else
5198             {
5199 7039         8370 $pair_counter = $global_pair_counter_offset_for_first_adjusted_choice[ $tally_adjusted_choice_for_choice_at_destination ] + $tally_adjusted_choice_for_choice_to_move ;
5200 7039 100       11074 if ( $direction_increment == 1 )
5201             {
5202 3710         4419 $tally_choice_to_move_over_choice_at_destination = $global_tally_second_over_first_in_pair[ $pair_counter ] ;
5203 3710         4933 $tally_choice_at_destination_over_choice_to_move = $global_tally_first_over_second_in_pair[ $pair_counter ] ;
5204             } else
5205             {
5206 3329         4190 $tally_choice_to_move_over_choice_at_destination = $global_tally_first_over_second_in_pair[ $pair_counter ] ;
5207 3329         10548 $tally_choice_at_destination_over_choice_to_move = $global_tally_second_over_first_in_pair[ $pair_counter ] ;
5208             }
5209             }
5210 13822 50       26585 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[tallies: " . $tally_choice_to_move_over_choice_at_destination . " " . $tally_choice_at_destination_over_choice_to_move . "]" } ;
  13822         34163  
5211 13822         16809 $score_increase += $tally_choice_to_move_over_choice_at_destination - $tally_choice_at_destination_over_choice_to_move ;
5212              
5213              
5214             #-----------------------------------------------
5215             # Keep track of which destination position
5216             # would increase the sequence score by the
5217             # largest positive amount, and regard that as
5218             # the expected destination.
5219             # If the choice being moved is at the same
5220             # ranking level as another choice -- because
5221             # it has the same sequence score -- then move
5222             # the choice to the higher level (left-most
5223             # position) so that the choices skip over
5224             # each other, which is the characteristic
5225             # that is used to keep track of equal
5226             # rankings.
5227              
5228 13822 100       26600 if ( $score_increase > 0 )
5229             {
5230 83         118 $pass_count_at_last_score_increase = $sort_pass_counter ;
5231 83 50       204 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[new highest score reached]" } ;
  83         169  
5232             }
5233 13822 100       26165 if ( $score_increase >= 0 )
5234             {
5235 1191 100       1962 if ( $score_increase > $largest_subset_sum )
    100          
5236             {
5237 896         891 $largest_subset_sum = $score_increase ;
5238 896         969 $actual_destination = $possible_destination ;
5239 896 50       1572 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[new largest subset sum is " . $largest_subset_sum . "]\n" } ;
  896         2999  
5240             } elsif ( $score_increase == $largest_subset_sum )
5241             {
5242 286         489 $actual_destination = $possible_destination ;
5243 286 50       561 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[equal tally sums, will move choice to farthest position]\n" } ;
  286         1167  
5244             } else
5245             {
5246 9 50       26 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[current subset sum (" . $score_increase . ") is not largest]\n" } ;
  9         34  
5247             }
5248             } else
5249             {
5250 12631 50       24514 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[subset sum (" . $score_increase . ") is negative]\n" } ;
  12631         46389  
5251             }
5252              
5253              
5254             #-----------------------------------------------
5255             # Repeat the loop that checks each position in
5256             # the sorted list as a possible destination for
5257             # the choice being moved.
5258              
5259             }
5260              
5261              
5262             #-----------------------------------------------
5263             # If the choice should remain where it is, skip
5264             # over the next few sections of code (that
5265             # would move the choice).
5266             # After the choices have stabilized into a
5267             # sorted sequence, this lack of movement will
5268             # be typical because a "move" from the
5269             # unsorted segment to the sorted segment does
5270             # not involve a change in the sequence position,
5271             # just a change in the boundary between the
5272             # sorted and sorted segments (which are
5273             # adjacent).
5274              
5275 4293 100       7073 if ( $position_of_choice_to_move == $actual_destination )
5276             {
5277 3404 50       6279 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in sort-pass loop, no need to move choice " . $actual_choice_to_move . "]\n" } ;
  3404         12397  
5278             } else
5279             {
5280              
5281              
5282             #-----------------------------------------------
5283             # Move the choice to the sequence position that
5284             # produces the biggest increase in the overall
5285             # sequence score.
5286             # For the choices being skipped over (by the
5287             # choice being moved), update their highest
5288             # or lowest sequence position value -- if the
5289             # move involves moving them outside of their
5290             # previous range.
5291              
5292 889 50       1712 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in sort-pass loop, need to move choice " . $actual_choice_to_move . " from position " . $position_of_choice_to_move . " to position " . $actual_destination . "]\n" } ;
  889         2400  
5293 889         916 $count_of_sequences_with_same_highest_score ++ ;
5294 889         1011 $sort_pass_count_at_last_move = $sort_pass_counter ;
5295 889 100       1417 if ( $direction_increment == 1 )
5296             {
5297 638         751 $number_of_choices_to_shift = $position_of_choice_to_move - $actual_destination ;
5298             } else
5299             {
5300 251         478 $number_of_choices_to_shift = $actual_destination - $position_of_choice_to_move ;
5301             }
5302 889         1874 for ( $position_number = 1 ; $position_number <= $number_of_choices_to_shift ; $position_number ++ )
5303             {
5304 1235 100       3122 if ( $direction_increment == 1 )
5305             {
5306 864         905 $from_position = $position_of_choice_to_move - $position_number ;
5307 864         1021 $to_position = $from_position + 1 ;
5308             } else
5309             {
5310 371         384 $from_position = $position_of_choice_to_move + $position_number ;
5311 371         485 $to_position = $from_position - 1 ;
5312             }
5313 1235         1487 $actual_choice = $actual_choice_in_insertion_rank_sequence_position[ $from_position ] ;
5314 1235         1439 $actual_choice_in_insertion_rank_sequence_position[ $to_position ] = $actual_choice ;
5315 1235         1350 $adjusted_choice = $local_adjusted_choice_for_actual_choice[ $actual_choice ] ;
5316 1235 100       2839 if ( $to_position > $lowest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice ] )
5317             {
5318 398         473 $lowest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice ] = $to_position ;
5319 398         585 $pass_number_at_last_rerank_for_adjusted_choice[ $adjusted_choice ] = $sort_pass_counter ;
5320             }
5321 1235 100       3854 if ( $to_position < $highest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice ] )
5322             {
5323 117         156 $highest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice ] = $to_position ;
5324 117         311 $pass_number_at_last_rerank_for_adjusted_choice[ $adjusted_choice ] = $sort_pass_counter ;
5325             }
5326             }
5327 889         1121 $actual_choice_in_insertion_rank_sequence_position[ $actual_destination ] = $actual_choice_to_move ;
5328              
5329              
5330             #-----------------------------------------------
5331             # For the choice being moved, update its highest
5332             # or lowest sequence position value -- if this
5333             # move involves moving it outside of its
5334             # previous range.
5335             # The highest-and-lowest position information
5336             # is needed to determine which choices are
5337             # repeatedly skipping over each other, and that
5338             # indicates which choices are tied, and at what
5339             # ranking levels.
5340              
5341 889 100       1697 if ( $actual_destination < $highest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice_to_move ] )
5342             {
5343 334         424 $highest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice_to_move ] = $actual_destination ;
5344 334         455 $pass_number_at_last_rerank_for_adjusted_choice[ $adjusted_choice_to_move ] = $sort_pass_counter ;
5345             }
5346 889 100       1896 if ( $actual_destination > $lowest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice_to_move ] )
5347             {
5348 91         147 $lowest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice_to_move ] = $actual_destination ;
5349 91         131 $pass_number_at_last_rerank_for_adjusted_choice[ $adjusted_choice_to_move ] = $sort_pass_counter ;
5350             }
5351              
5352              
5353             #-----------------------------------------------
5354             # For debugging, display the tally numbers in
5355             # an array/matrix arrangement.
5356              
5357 889 50       1609 if ( $true_or_false_log_details == $global_true )
5358             {
5359 889 100       1421 if ( $local_adjusted_choice_count == $global_adjusted_choice_count )
5360             {
5361 463         1037 for ( $sequence_position = 1 ; $sequence_position <= $local_adjusted_choice_count ; $sequence_position ++ )
5362             {
5363 3144         3955 $actual_choice = $actual_choice_in_insertion_rank_sequence_position[ $sequence_position ] ;
5364 3144         6947 $global_log_info_choice_at_position[ $sequence_position ] = $actual_choice ;
5365             }
5366 463         901 &internal_view_matrix( ) ;
5367 463 100       1851 if ( $global_sequence_score > $global_sequence_score_using_insertion_sort_method )
5368             {
5369 85         132 $global_sequence_score_using_insertion_sort_method = $global_sequence_score ;
5370 85         719 print LOGOUT "\n[insertion sort, new sequence score is: " . $global_sequence_score_using_insertion_sort_method . "]\n" ;
5371             }
5372             } else
5373             {
5374 426         669 print LOGOUT "\n[insertion sort, current sub-sort sequence is: " ;
5375 426         919 for ( $sequence_position = 1 ; $sequence_position <= $local_adjusted_choice_count ; $sequence_position ++ )
5376             {
5377 2504         2875 $actual_choice = $actual_choice_in_insertion_rank_sequence_position[ $sequence_position ] ;
5378 2504         6085 print LOGOUT $actual_choice . " , " ;
5379             }
5380 426         1362 print LOGOUT "]\n" ;
5381             }
5382             }
5383              
5384              
5385             #-----------------------------------------------
5386             # Finish skipping the code that moves a choice
5387             # to a new sequence position.
5388              
5389             }
5390              
5391              
5392             #-----------------------------------------------
5393             # Repeat the loop that moves each unsorted choice
5394             # into the sorted segment.
5395              
5396             }
5397              
5398              
5399             #-----------------------------------------------
5400             # For debugging, display the highest and lowest
5401             # rankings -- unless the values are about to be
5402             # reset.
5403              
5404 1146 50       2058 if ( $true_or_false_log_details == $global_true )
5405             {
5406 1146 100       2204 if ( $sort_pass_counter != $pass_count_at_last_score_increase )
5407             {
5408 1097         1341 print LOGOUT "\n" ;
5409 1097         2670 for ( $adjusted_choice = 1 ; $adjusted_choice <= $local_adjusted_choice_count ; $adjusted_choice ++ )
5410             {
5411 5436         6063 $actual_choice = $local_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
5412 5436         5754 $highest_rank = $highest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice ] ;
5413 5436         7311 $lowest_rank = $lowest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice ] ;
5414 5436         20802 print LOGOUT "[insertion sort, in sort-pass loop, choice " . $actual_choice . " has been at highest " . $highest_rank . " and lowest " . $lowest_rank . "]\n" ;
5415             }
5416             }
5417             }
5418              
5419              
5420             #-----------------------------------------------
5421             # If the total score increased during this
5422             # sorting pass, reset the highest and lowest
5423             # sequence-position values according to the
5424             # current sort order, and reset the flag
5425             # that might have indicated a stable condition.
5426              
5427 1146 100       2262 if ( $sort_pass_counter == $pass_count_at_last_score_increase )
5428             {
5429 49 50       135 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "\n[insertion sort, in sort-pass loop, score increased during this pass, so initializing highest and lowest positions for all choices]\n" } ;
  49         102  
5430 49         67 $reached_stable_condition_at_pass_count = 0 ;
5431 49         54 $count_of_sequences_with_same_highest_score = 0 ;
5432 49         162 for ( $sequence_position = 1 ; $sequence_position <= $local_adjusted_choice_count ; $sequence_position ++ )
5433             {
5434 364         417 $actual_choice = $actual_choice_in_insertion_rank_sequence_position[ $sequence_position ] ;
5435 364         400 $adjusted_choice = $local_adjusted_choice_for_actual_choice[ $actual_choice ] ;
5436 364         384 $highest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice ] = $sequence_position ;
5437 364         793 $lowest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice ] = $sequence_position ;
5438             }
5439             }
5440              
5441              
5442             #-----------------------------------------------
5443             # Log the movement of any choices during this
5444             # sorting pass.
5445              
5446 1146 50       2154 if ( $true_or_false_log_details == $global_true )
5447             {
5448 1146 100       2001 if ( $sort_pass_count_at_last_move == $sort_pass_counter )
5449             {
5450 590         897 print LOGOUT "\n[insertion sort, in sort-pass loop, at least one choice moved during this sorting pass]\n" ;
5451             } else
5452             {
5453 556         1061 print LOGOUT "\n[insertion sort, in sort-pass loop, no choices moved during this sorting pass]\n" ;
5454             }
5455              
5456 1146         2363 for ( $adjusted_choice = 1 ; $adjusted_choice <= $local_adjusted_choice_count ; $adjusted_choice ++ )
5457             {
5458 5800         6473 $pass_number = $pass_number_at_last_rerank_for_adjusted_choice[ $adjusted_choice ] ;
5459 5800 100       15042 if ( $pass_number == $sort_pass_counter )
5460             {
5461 968         1015 $actual_choice = $local_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
5462 968         3129 print LOGOUT "[insertion sort, in sort-pass loop, choice " . $actual_choice . " moved during this pass]\n" ;
5463             }
5464             }
5465 1146         3447 print LOGOUT "\n" ;
5466             }
5467              
5468              
5469             #-----------------------------------------------
5470             # Repeat the loop that sorts the choices (until
5471             # they stabilize).
5472              
5473             }
5474              
5475              
5476             #-----------------------------------------------
5477             # Log the ending sequence.
5478              
5479 245 50       490 if ( $true_or_false_log_details == $global_true )
5480             {
5481 245         386 print LOGOUT "\n[insertion sort, in main loop, ending sequence is: " ;
5482 245         603 for ( $sequence_position = 1 ; $sequence_position <= $local_adjusted_choice_count ; $sequence_position ++ )
5483             {
5484 1166         1346 $actual_choice = $actual_choice_in_insertion_rank_sequence_position[ $sequence_position ] ;
5485 1166         2861 print LOGOUT $actual_choice . " , " ;
5486             }
5487 245         350 print LOGOUT "]\n" ;
5488             }
5489              
5490              
5491             #-----------------------------------------------
5492             # If only one sequence has the highest sequence
5493             # score, do not do any sub-set sorting (to
5494             # ensure finding correct most-popular choice).
5495              
5496 245 100 100     5776 if ( ( $main_loop_count == 1 ) && ( $count_of_sequences_with_same_highest_score == 1 ) )
5497             {
5498 20 50       66 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in main loop, only one sequence has highest sequence score, so exiting main loop]\n" } ;
  20         30  
5499 20         46 last ;
5500             }
5501              
5502              
5503             #-----------------------------------------------
5504             # If this is the final stage, put the highest-
5505             # ranked choice (or choices) back into the full
5506             # sequence, at the highest ranking.
5507             # Also adjust the values that keep track of
5508             # each choice's highest and lowest positions.
5509              
5510 225 100       1075 if ( $final_stage_reached_at_main_loop_count == $main_loop_count )
5511             {
5512 55 50       131 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in main loop, wrapping up final stage]\n" } ;
  55         75  
5513 55         109 $source_sequence_position = $local_adjusted_choice_count ;
5514 55         194 for ( $destination_sequence_position = $global_adjusted_choice_count ; $destination_sequence_position >= $global_adjusted_choice_count - $local_adjusted_choice_count + 1 ; $destination_sequence_position -- )
5515             {
5516 296         391 $actual_choice_to_move = $actual_choice_in_insertion_rank_sequence_position[ $source_sequence_position ] ;
5517 296 50       564 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[lower choice " . $actual_choice_to_move . " is restored to adjusted choice " . $adjusted_choice_to_move . "]\n" } ;
  296         693  
5518 296         404 $actual_choice_in_insertion_rank_sequence_position[ $destination_sequence_position ] = $actual_choice_to_move ;
5519 296         350 $adjusted_choice_to_move = $global_adjusted_choice_for_actual_choice[ $actual_choice_to_move ] ;
5520 296         384 $highest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice_to_move ] += $global_adjusted_choice_count - $local_adjusted_choice_count ;
5521 296         352 $lowest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice_to_move ] += $global_adjusted_choice_count - $local_adjusted_choice_count ;
5522 296 50       606 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[choice " . $actual_choice_to_move . " has highest sequence position " . $highest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice_to_move ] . " and lowest sequence position " . $lowest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice_to_move ] . "]\n" } ;
  296         1128  
5523 296         771 $source_sequence_position -- ;
5524             }
5525 55         194 for ( $destination_sequence_position = 1 ; $destination_sequence_position <= $count_of_highest_ranked_choices ; $destination_sequence_position ++ )
5526             {
5527 67         104 $choice_counter = $destination_sequence_position ;
5528 67         118 $actual_choice = $highest_ranked_actual_choice_at_count[ $choice_counter ] ;
5529 67         127 $actual_choice_in_insertion_rank_sequence_position[ $destination_sequence_position ] = $actual_choice ;
5530 67         76 $adjusted_choice = $global_adjusted_choice_for_actual_choice[ $actual_choice ] ;
5531 67 50       153 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[highest choice " . $actual_choice . " is restored to adjusted choice " . $adjusted_choice . "]\n" } ;
  67         335  
5532             }
5533 55 50       155 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, in main loop, done with final stage, exiting main loop]\n" } ;
  55         94  
5534 55         110 last ;
5535             }
5536              
5537              
5538             #-----------------------------------------------
5539             # Repeat the loop to do the next stage of
5540             # calculations.
5541              
5542             }
5543              
5544              
5545             #-----------------------------------------------
5546             # If, at the end of the multiple sorting
5547             # passes, any of the choices were still moving,
5548             # this indicates that some choices are tied (at
5549             # the same ranking level), so determine
5550             # which choices are tied, and at which levels.
5551             # If no choices have moved, use the following
5552             # code anyway because it normalizes the
5553             # ranking levels.
5554             # For each choice, multiply the sum of
5555             # the highest and lowest ranking level by
5556             # a constant (10 times the number of choices minus one)
5557             # and convert the result to an integer.
5558             # Use these "averaged scaled integerized"
5559             # ranking levels to calculate normalized
5560             # (and normal) ranking levels, where
5561             # choices are ranked at the same level if
5562             # they have the same
5563             # averaged-scaled-integerized values.
5564              
5565 84 50       205 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, calculating averaged-scaled-integerized levels]\n" } ;
  84         164  
5566 84         146 $scale_value = 10 * ( $global_adjusted_choice_count - 1 ) ;
5567 84         244 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
5568             {
5569 475         581 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
5570 475         534 $highest_rank = $highest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice ] ;
5571 475         547 $lowest_rank = $lowest_insertion_sort_sequence_position_for_actual_choice[ $actual_choice ] ;
5572 475 50       877 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, done, choice " . $actual_choice . " has been at highest rank level " . $highest_rank . " and lowest rank level " . $lowest_rank . "]\n" } ;
  475         1285  
5573 475         607 $special_ranking_level = int( ( $highest_rank + $lowest_rank ) * $scale_value ) ;
5574 475         620 $global_rank_to_normalize_for_adjusted_choice[ $adjusted_choice ] = $special_ranking_level ;
5575 475 50       893 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, choice " . $actual_choice . " at special rank level " . $special_ranking_level . "]\n" } ;
  475         1800  
5576             }
5577 84         293 &normalize_ranking( ) ;
5578 84 50       242 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, final normalized ranking levels]\n" } ;
  84         171  
5579 84         242 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
5580             {
5581 475         573 $ranking_level = $global_rank_to_normalize_for_adjusted_choice[ $adjusted_choice ] ;
5582 475         507 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
5583 475         578 $global_insertion_sort_popularity_rank_for_actual_choice[ $actual_choice ] = $ranking_level ;
5584 475 50       943 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[insertion sort, choice " . $actual_choice . " at normalized rank level " . $ranking_level . "]\n" } ;
  475         5972  
5585             }
5586              
5587              
5588             #-----------------------------------------------
5589             # For debugging, display the tally numbers in
5590             # an array/matrix arrangement.
5591             # Use the sequence that was determined when
5592             # normalization was done.
5593              
5594 84 50       356 if ( $true_or_false_log_details == $global_true )
5595             {
5596 84         247 print LOGOUT "[insertion sort, final insertion-sort popularity ranking:]\n" ;
5597 84         407 &internal_view_matrix( ) ;
5598 84 100       215 if ( $global_sequence_score > $global_sequence_score_using_insertion_sort_method )
5599             {
5600 17         23 $global_sequence_score_using_insertion_sort_method = $global_sequence_score ;
5601 17         65 print LOGOUT "\n[insertion sort, new sequence score is: " . $global_sequence_score_using_insertion_sort_method . "]\n" ;
5602             }
5603             }
5604              
5605              
5606             #-----------------------------------------------
5607             # Log the calculated ranking levels.
5608              
5609 84 50       267 if ( $true_or_false_log_details == $global_true )
5610             {
5611 84         135 print LOGOUT "[insertion sort, final results:]\n" ;
5612 84         223 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
5613             {
5614 475         535 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
5615 475         1656 print LOGOUT "[ choice " . $actual_choice . " is at ranking level " . $global_insertion_sort_popularity_rank_for_actual_choice[ $actual_choice ] . "]\n" ;
5616             }
5617             }
5618              
5619              
5620             #-----------------------------------------------
5621             # End of subroutine.
5622              
5623 84 50       178 if ( $global_logging_info == $global_true ) { print LOGOUT "[insertion sort, exiting calc_votefair_insertion_sort_popularity_rank subroutine]\n\n" } ;
  84         215  
5624 84         562 return "" ;
5625              
5626             }
5627              
5628              
5629              
5630              
5631             =head2 calc_all_sequence_scores
5632              
5633             (Not exported, for internal use only.)
5634              
5635             Calculates VoteFair popularity ranking
5636             results by calculating every sequence score to
5637             find the highest score, and regarding the
5638             sequence (ranking) with the highest score to be
5639             the overall ranking. For details, see
5640             www.VoteFair.org or Wikipedia's
5641             "Condorcet-Kemeny method" article (which
5642             currently redirects to the "Kemeny-Young method"
5643             article) or the book titled "Ending The Hidden
5644             Unfairness In U.S. Elections".
5645              
5646             If multiple sequences have the same highest score,
5647             calculate the average sequence position for each
5648             choice (but only for the sequences that have the
5649             highest score), and then normalize (remove gaps
5650             from) those rankings.
5651              
5652             =cut
5653              
5654             #-----------------------------------------------
5655             #-----------------------------------------------
5656             # calc_all_sequence_scores
5657             #-----------------------------------------------
5658             #-----------------------------------------------
5659              
5660             sub calc_all_sequence_scores
5661             {
5662              
5663 56     56 1 107 my $score ;
5664             my $highest_score ;
5665 0         0 my $actual_choice ;
5666 0         0 my $adjusted_choice ;
5667 0         0 my $first_choice_number ;
5668 0         0 my $second_choice_number ;
5669 0         0 my $position_in_sequence ;
5670 0         0 my $position_to_shift ;
5671 0         0 my $sequence_count ;
5672 0         0 my $sequence_position ;
5673 0         0 my $removal_position ;
5674 0         0 my $pair_counter ;
5675 0         0 my $counter ;
5676 0         0 my $sequence_info ;
5677 0         0 my $ranking_info ;
5678 0         0 my $ranking_changes_info ;
5679 0         0 my $score_info ;
5680 0         0 my $main_loop_count ;
5681 0         0 my $ranking_level ;
5682 0         0 my $true_or_false_continue_loop ;
5683 0         0 my $true_or_false_log_details ;
5684 0         0 my $true_or_false_log_all_sequences_details ;
5685 0         0 my $top_down_rank ;
5686 0         0 my $bottom_up_rank ;
5687 0         0 my $average ;
5688 0         0 my $count_of_same_highest_score ;
5689              
5690 0         0 my @sequence_count_at_position ;
5691 0         0 my @maximum_sequence_count_at_position ;
5692 0         0 my @sequence_position_for_adjusted_choice ;
5693 0         0 my @count_of_sequences_with_highest_ranking_for_adjusted_choice ;
5694 0         0 my @count_of_sequences_with_lowest_ranking_for_adjusted_choice ;
5695 0         0 my @sum_of_rankings_at_highest_score_for_adjusted_choice ;
5696 0         0 my @count_of_rankings_at_highest_score_for_adjusted_choice ;
5697 0         0 my @choice_in_remainder_position ;
5698              
5699              
5700             #-----------------------------------------------
5701             # Hide or show the details in the log file.
5702              
5703 56         70 $true_or_false_log_details = $global_true ;
5704 56         70 $true_or_false_log_all_sequences_details = $global_false ;
5705 56 50       136 if ( $global_logging_info == $global_false )
5706             {
5707 0         0 $true_or_false_log_details = $global_false ;
5708             }
5709 56 50       155 if ( $true_or_false_log_details == $global_false )
5710             {
5711 0         0 $true_or_false_log_all_sequences_details = $global_false ;
5712             }
5713 56 50       139 if ( $global_logging_info == $global_true )
5714             {
5715 56         72 print LOGOUT "[all scores, beginning calc_all_sequence_scores subroutine]\n\n" ;
5716 56 50       111 if ( $true_or_false_log_details == $global_true )
5717             {
5718 56         82 print LOGOUT "[all scores, some details shown (change flag value to hide details)]\n" ;
5719 56 50       117 if ( $true_or_false_log_all_sequences_details == $global_false )
5720             {
5721 56         97 print LOGOUT "[all scores, details for every sequence hidden (change flag value to view details)]\n" ;
5722             }
5723             } else
5724             {
5725 0         0 print LOGOUT "[all scores, details hidden (change flag value to view details)]\n" ;
5726             }
5727             }
5728              
5729              
5730             #-----------------------------------------------
5731             # In case of an early error, initialize the
5732             # ranking of each choice -- to zero.
5733              
5734 56         137 for ( $adjusted_choice = 1; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
5735             {
5736 238         275 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
5737 238         625 $global_popularity_ranking_for_actual_choice[ $actual_choice ] = 0 ;
5738             }
5739              
5740              
5741             #-----------------------------------------------
5742             # If there are not at least two choices,
5743             # there is a program bug because that should
5744             # have already been checked.
5745              
5746 56 50       150 if ( $global_adjusted_choice_count < 2 )
5747             {
5748 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[all scores, ERROR: number of (adjusted) choices is less than two]\n" } ;
  0         0  
5749 0         0 warn "program bug, there was an attempt to rank only a single choice" ;
5750 0         0 return ;
5751             }
5752              
5753              
5754             #-----------------------------------------------
5755             # If there are too many choices, indicate an
5756             # error.
5757              
5758 56 50       135 if ( $global_adjusted_choice_count > $global_check_all_scores_choice_limit )
5759             {
5760 0         0 $global_output_warning_messages_case_or_question_specific .= $global_question_specific_warning_begin . " has-too-many-choices-for-this-software-version-so-VoteFair-calculations-cannot-be-done" . "\n-----\n\n" ;
5761 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[all scores, ERROR: number of (adjusted) choices exceeds limit (" . $global_check_all_scores_choice_limit . ")]\n" } ;
  0         0  
5762 0         0 return ;
5763             }
5764              
5765              
5766             #-----------------------------------------------
5767             # Initialize the ranking information that is
5768             # tracked for each choice.
5769             # Initialize the counter that counts how many
5770             # sequences have the same highest sequence
5771             # score. Also initialize the sum that adds the
5772             # ranking-sequence levels at which a highest
5773             # sequence score occurs. If there is only one
5774             # sequence with the highest score, this sum
5775             # will equal that sequence position.
5776             #
5777             # Also, for comparison purposes, initialize
5778             # two other rank-tracking values. One such
5779             # value tracks the highest ranking
5780             # encountered (in a highest-score sequence),
5781             # and the other value tracks the lowest
5782             # ranking encountered (in a highest-score
5783             # sequence). Also initialize the counts of
5784             # how many sequences have these highest or
5785             # lowest rankings.
5786              
5787 56 50       132 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[all scores, beginning to calculate VoteFair popularity results]\n" } ;
  56         97  
5788 56         140 for ( $adjusted_choice = 1; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
5789             {
5790 238         270 $count_of_rankings_at_highest_score_for_adjusted_choice[ $adjusted_choice ] = 0 ;
5791 238         278 $sum_of_rankings_at_highest_score_for_adjusted_choice[ $adjusted_choice ] = 0 ;
5792 238         322 $global_adjusted_ranking_for_adjusted_choice_bottom_up_version[ $adjusted_choice ] = $global_adjusted_choice_count + 1 ;
5793 238         267 $global_adjusted_ranking_for_adjusted_choice_top_down_version[ $adjusted_choice ] = 0 ;
5794 238         260 $count_of_sequences_with_highest_ranking_for_adjusted_choice[ $adjusted_choice ] = 0 ;
5795 238         567 $count_of_sequences_with_lowest_ranking_for_adjusted_choice[ $adjusted_choice ] = 0 ;
5796             }
5797              
5798              
5799             #-----------------------------------------------
5800             # Calculate the number of possible sequences to
5801             # check, and log this number.
5802              
5803 56 50       131 if ( $true_or_false_log_details == $global_true )
5804             {
5805 56         73 $sequence_count = 1 ;
5806 56         154 for ( $counter = 2 ; $counter <= $global_adjusted_choice_count ; $counter ++ )
5807             {
5808 182         375 $sequence_count = $sequence_count * $counter ;
5809             }
5810 56         151 print LOGOUT "[all scores, number of sequences to check is " . $sequence_count . "]" ;
5811             }
5812              
5813              
5814             #-----------------------------------------------
5815             # Initialize a list of numbers that will be
5816             # used to cycle through all the possible
5817             # sequences. Also specify the maximum count
5818             # value that is allowed for each position in that list.
5819              
5820 56         135 for ( $sequence_position = 1 ; $sequence_position <= $global_adjusted_choice_count ; $sequence_position ++ )
5821             {
5822 238         286 $sequence_count_at_position[ $sequence_position ] = 1 ;
5823 238         571 $maximum_sequence_count_at_position[ $sequence_position ] = $global_adjusted_choice_count - $sequence_position + 1 ;
5824             }
5825 56 50       118 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "\n" } ;
  56         98  
5826              
5827              
5828             #-----------------------------------------------
5829             # Begin a loop that checks each possible
5830             # sequence, in terms of which choice is first,
5831             # which is second, etc.
5832              
5833 56         65 $main_loop_count = 0 ;
5834 56         63 $true_or_false_continue_loop = $global_true ;
5835 56         70 $highest_score = 0 ;
5836 56         99 $count_of_same_highest_score = 0 ;
5837 56         124 while ( $true_or_false_continue_loop == $global_true )
5838             {
5839 11132         10882 $main_loop_count ++ ;
5840 11132 50       21136 if ( $main_loop_count > 10000 )
5841             {
5842 0         0 $global_output_warning_messages_case_or_question_specific .= $global_question_specific_warning_begin . " has-too-many-choices-so-plurality-counting-done" . "\n-----\n\n" ;
5843 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[all scores, Warning: Too many choices (" . $global_adjusted_choice_count . "), so only plurality results calculated]\n" } ;
  0         0  
5844 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[all scores, exiting main loop early]" } ;
  0         0  
5845 0         0 return ;
5846             }
5847              
5848              
5849             #-----------------------------------------------
5850             # Initialize some debug text strings.
5851              
5852 11132         12520 $sequence_info = " sequence: " ;
5853 11132         12488 $ranking_info = " ranking: " ;
5854 11132         11247 $ranking_changes_info = "" ;
5855 11132         17092 @global_log_info_choice_at_position = ( ) ;
5856              
5857              
5858             #-----------------------------------------------
5859             # Put all the choice numbers into a
5860             # number-ordered list named
5861             # "choice_in_remainder_position".
5862              
5863 11132         23112 for ( $sequence_position = 1 ; $sequence_position <= $global_adjusted_choice_count ; $sequence_position ++ )
5864             {
5865 64486         61922 $adjusted_choice = $sequence_position ;
5866 64486         130581 $choice_in_remainder_position[ $sequence_position ] = $adjusted_choice ;
5867             }
5868              
5869              
5870             #-----------------------------------------------
5871             # Generate the current sequence of choice numbers.
5872             # Put them in the list named
5873             # "sequence_position_for_adjusted_choice".
5874             # Base the sequence on the counters in the
5875             # counter list named "sequence_count_at_position".
5876             # While creating this, use the
5877             # "choice_in_remainder_position" list
5878             # to keep track of which choice numbers have
5879             # not yet been used in the sequence.
5880              
5881 11132         22205 for ( $sequence_position = 1 ; $sequence_position <= $global_adjusted_choice_count ; $sequence_position ++ )
5882             {
5883 64486         70547 $removal_position = $sequence_count_at_position[ $sequence_position ] ;
5884 64486         66719 $adjusted_choice = $choice_in_remainder_position[ $removal_position ] ;
5885 64486         79522 $sequence_info .= $adjusted_choice . " , " ;
5886 64486         80130 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
5887 64486         81482 $global_log_info_choice_at_position[ $sequence_position ] = $actual_choice ;
5888 64486         86882 $sequence_position_for_adjusted_choice[ $adjusted_choice ] = $sequence_position ;
5889 64486         177140 for ( $position_to_shift = $removal_position ; $position_to_shift <= $global_adjusted_choice_count - $sequence_position ; $position_to_shift ++ )
5890             {
5891 78040         225187 $choice_in_remainder_position[ $position_to_shift ] = $choice_in_remainder_position[ $position_to_shift + 1 ] ;
5892             }
5893             }
5894              
5895              
5896             #-----------------------------------------------
5897             # Calculate the score for the current sequence.
5898             # It equals the sum of all the pairwise counts
5899             # (tally-table numbers) that apply to the
5900             # sequence.
5901              
5902 11132         11772 $score = 0 ;
5903 11132         21920 for ( $pair_counter = 1 ; $pair_counter <= $global_pair_counter_maximum ; $pair_counter ++ )
5904             {
5905 156080         164046 $first_choice_number = $global_adjusted_first_choice_number_in_pair[ $pair_counter ] ;
5906 156080         161423 $second_choice_number = $global_adjusted_second_choice_number_in_pair[ $pair_counter ] ;
5907 156080 100       246667 if ( $sequence_position_for_adjusted_choice[ $first_choice_number ] < $sequence_position_for_adjusted_choice[ $second_choice_number ] )
5908             {
5909 78040         173726 $score += $global_tally_first_over_second_in_pair[ $pair_counter ] ;
5910             } else
5911             {
5912 78040         179148 $score += $global_tally_second_over_first_in_pair[ $pair_counter ] ;
5913             }
5914             }
5915 11132         14437 $score_info = "score = " . $score ;
5916              
5917              
5918             #-----------------------------------------------
5919             # If the new score exceeds the previously
5920             # highest score, save this sequence as (so far)
5921             # having the highest score.
5922             # Also use the current sequence position as the
5923             # ranking position of each choice.
5924              
5925 11132 100       20846 if ( $score >= $highest_score )
5926             {
5927 544 100       914 if ( $score > $highest_score )
5928             {
5929 268         343 $highest_score = $score ;
5930 268         287 $count_of_same_highest_score = 1 ;
5931 268         550 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
5932             {
5933 1375         1619 $sequence_position = $sequence_position_for_adjusted_choice[ $adjusted_choice ] ;
5934 1375         1550 $count_of_rankings_at_highest_score_for_adjusted_choice[ $adjusted_choice ] = 1 ;
5935 1375         1611 $sum_of_rankings_at_highest_score_for_adjusted_choice[ $adjusted_choice ] = $sequence_position ;
5936 1375         1490 $global_adjusted_ranking_for_adjusted_choice_top_down_version[ $adjusted_choice ] = $sequence_position ;
5937 1375         1420 $global_adjusted_ranking_for_adjusted_choice_bottom_up_version[ $adjusted_choice ] = $sequence_position ;
5938 1375         1589 $count_of_sequences_with_highest_ranking_for_adjusted_choice[ $adjusted_choice ] = 1 ;
5939 1375         1436 $count_of_sequences_with_lowest_ranking_for_adjusted_choice[ $adjusted_choice ] = 1 ;
5940 1375         1795 $ranking_info .= $global_adjusted_ranking_for_adjusted_choice_top_down_version[ $adjusted_choice ] . " ; " ;
5941 1375         4044 $ranking_changes_info .= " ranking of " . $adjusted_choice . " set to " . $sequence_position . "\n" ;
5942             }
5943              
5944              
5945             #-----------------------------------------------
5946             # If the new score equals the previously highest
5947             # score, adjust the ranking level of any choices
5948             # that are in less-preferred (for top-down) or
5949             # most-preferred (for bottom-up) ranking positions
5950             # compared to the previous sequence with the
5951             # same highest score.
5952              
5953             } else
5954             {
5955 276         285 $count_of_same_highest_score ++ ;
5956 276         591 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
5957             {
5958 1443         1539 $sequence_position = $sequence_position_for_adjusted_choice[ $adjusted_choice ] ;
5959 1443         1858 $ranking_info .= $global_adjusted_ranking_for_adjusted_choice_top_down_version[ $adjusted_choice ] . " , " ;
5960 1443         1640 $sum_of_rankings_at_highest_score_for_adjusted_choice[ $adjusted_choice ] += $sequence_position ;
5961 1443         1447 $count_of_rankings_at_highest_score_for_adjusted_choice[ $adjusted_choice ] ++ ;
5962 1443 100       2759 if ( $sequence_position > $global_adjusted_ranking_for_adjusted_choice_top_down_version[ $adjusted_choice ] )
5963             {
5964 228         283 $global_adjusted_ranking_for_adjusted_choice_top_down_version[ $adjusted_choice ] = $sequence_position ;
5965 228         476 $ranking_changes_info .= " top-down ranking of " . $adjusted_choice . " reduced to " . $sequence_position . "\n" ;
5966 228         290 $count_of_sequences_with_lowest_ranking_for_adjusted_choice[ $adjusted_choice ] ++ ;
5967             }
5968 1443 100       4176 if ( $sequence_position < $global_adjusted_ranking_for_adjusted_choice_bottom_up_version[ $adjusted_choice ] )
5969             {
5970 247         314 $global_adjusted_ranking_for_adjusted_choice_bottom_up_version[ $adjusted_choice ] = $sequence_position ;
5971 247         478 $ranking_changes_info .= " bottom-up ranking of " . $adjusted_choice . " increased to " . $sequence_position . "\n" ;
5972 247         633 $count_of_sequences_with_highest_ranking_for_adjusted_choice[ $adjusted_choice ] ++ ;
5973             }
5974             }
5975             }
5976              
5977             #-----------------------------------------------
5978             # If the current score equals or exceeds the
5979             # previously highest score, log this information.
5980              
5981 544         1219 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
5982             {
5983 2818         2940 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
5984 2818         2776 $sequence_position = $sequence_position_for_adjusted_choice[ $adjusted_choice ] ;
5985 2818         5924 $global_log_info_choice_at_position[ $sequence_position ] = $actual_choice ;
5986             }
5987 544 50 33     2268 if ( ( $true_or_false_log_details == $global_true ) && ( $global_adjusted_choice_count <= 8 ) )
5988             {
5989 544         907 print LOGOUT "[all scores, sequence " ;
5990 544         1165 for ( $sequence_position = 1 ; $sequence_position <= $global_adjusted_choice_count ; $sequence_position ++ )
5991             {
5992 2818         3000 $actual_choice = $global_log_info_choice_at_position[ $sequence_position ] ;
5993 2818         6928 print LOGOUT $actual_choice . " , " ;
5994             }
5995 544         1131 print LOGOUT " has high score of " . $highest_score . "]\n" ;
5996 544 100       2328 if ( $main_loop_count == 1 )
5997             {
5998 56         252 $global_sequence_score_using_all_scores_method = 0 ;
5999             }
6000 544         893 print LOGOUT "[all scores, current top or score-matched ranking:]\n" ;
6001 544         971 &internal_view_matrix( ) ;
6002 544         898 $global_sequence_score_using_all_scores_method = $global_sequence_score ;
6003             }
6004              
6005              
6006             #-----------------------------------------------
6007             # Finish skipping over the sections that handle
6008             # a highest score.
6009              
6010             }
6011              
6012              
6013             #-----------------------------------------------
6014             # For debugging, display some key info -- for
6015             # every sequence checked.
6016              
6017 11132 50 33     25712 if ( ( $true_or_false_log_all_sequences_details == $global_true ) && ( $global_adjusted_choice_count <= 8 ) )
6018             {
6019 0         0 print LOGOUT $sequence_info . " " . $score_info . "\n" ;
6020 0         0 print LOGOUT $ranking_info . "\n" ;
6021 0         0 print LOGOUT $ranking_changes_info . "\n" ;
6022             }
6023              
6024              
6025             #-----------------------------------------------
6026             # Update the counters that are used to identify
6027             # the next sequence to be considered.
6028             # These counters are also used to identify when
6029             # all the sequences have been checked.
6030              
6031 11132         11289 $position_in_sequence = $global_adjusted_choice_count - 1 ;
6032 11132         21873 while ( $position_in_sequence > 0 )
6033             {
6034 19058         20619 $sequence_count_at_position[ $position_in_sequence ] ++ ;
6035 19058 100       40036 if ( $sequence_count_at_position[ $position_in_sequence ] > $maximum_sequence_count_at_position[ $position_in_sequence ] )
6036             {
6037 7982         8624 $sequence_count_at_position[ $position_in_sequence ] = 1 ;
6038 7982         15439 $position_in_sequence -- ;
6039 7982 100       23531 if ( $position_in_sequence == 0 )
6040             {
6041 56         243 $true_or_false_continue_loop = $global_false ;
6042             }
6043             } else
6044             {
6045 11076         37703 $position_in_sequence = 0 ;
6046             }
6047             }
6048              
6049              
6050             #-----------------------------------------------
6051             # Repeat the loop to check the next sequence.
6052              
6053             }
6054              
6055              
6056             #-----------------------------------------------
6057             # For each choice, calculate the average
6058             # ranking for the sequences in which the score
6059             # was the highest score. However, scale those
6060             # averages by the number of adjusted choices
6061             # minus one so that integer numbers can be
6062             # used. Then normalize those values to produce
6063             # the final ranking. Also, log the highest and
6064             # lowest ranking positions -- for the sequences
6065             # that have the same highest sequence score.
6066              
6067 56 50       129 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[all scores, count of same highest score is " . $count_of_same_highest_score . "]\n" } ;
  56         321  
6068 56 50       147 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[all scores, top-down and bottom-up and scaled-average values:]\n" } ;
  56         118  
6069 56         165 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
6070             {
6071 238         307 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
6072 238         302 $top_down_rank = $global_adjusted_ranking_for_adjusted_choice_top_down_version[ $adjusted_choice ] ;
6073 238         269 $bottom_up_rank = $global_adjusted_ranking_for_adjusted_choice_bottom_up_version[ $adjusted_choice ] ;
6074 238         517 $average = int( ( ( $global_adjusted_choice_count - 1 ) * $sum_of_rankings_at_highest_score_for_adjusted_choice[ $adjusted_choice ] ) / $count_of_rankings_at_highest_score_for_adjusted_choice[ $adjusted_choice ] ) ;
6075 238 50       447 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[ choice " . $actual_choice . " , top-down ranking is " . $top_down_rank . " (for " . $count_of_sequences_with_highest_ranking_for_adjusted_choice[ $adjusted_choice ] . " scores) , bottom-up ranking is " . $bottom_up_rank . " (for " . $count_of_sequences_with_lowest_ranking_for_adjusted_choice[ $adjusted_choice ] . " scores) , scaled average " . $average . "]\n" } ;
  238         1218  
6076 238         688 $global_rank_to_normalize_for_adjusted_choice[ $adjusted_choice ] = $average ;
6077             }
6078 56         242 &normalize_ranking( ) ;
6079 56 50       209 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[all scores, final normalized results:]\n" } ;
  56         184  
6080 56         161 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
6081             {
6082 238         277 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
6083 238         246 $ranking_level = $global_rank_to_normalize_for_adjusted_choice[ $adjusted_choice ] ;
6084 238         318 $global_popularity_ranking_for_actual_choice[ $actual_choice ] = $ranking_level ;
6085 238 50       406 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[ choice " . $actual_choice . " is at top-down popularity level " . $ranking_level . "]\n" } ;
  238         984  
6086             }
6087              
6088              
6089             #-----------------------------------------------
6090             # For debugging, display the tally numbers in
6091             # an array/matrix arrangement.
6092             # Use the sequence that was determined when
6093             # normalization was done.
6094              
6095 56         78 $true_or_false_log_details = $global_true ;
6096 56 50       138 if ( $true_or_false_log_details == $global_true )
6097             {
6098 56         234 print LOGOUT "[all scores, final popularity ranking:]\n" ;
6099 56         108 &internal_view_matrix( ) ;
6100             }
6101              
6102              
6103             #-----------------------------------------------
6104             # End of subroutine.
6105              
6106 56 50       146 if ( $global_logging_info == $global_true ) { print LOGOUT "[all scores, exiting calc_all_sequence_scores subroutine]\n\n" } ;
  56         285  
6107 56         298 return 1 ;
6108              
6109             }
6110              
6111              
6112              
6113              
6114             =head2 compare_popularity_results
6115              
6116             (Not exported, for internal use only.)
6117              
6118             Compares the results of different methods for
6119             calculating VoteFair popularity ranking.
6120              
6121             =cut
6122              
6123             #-----------------------------------------------
6124             #-----------------------------------------------
6125             # compare_popularity_results
6126             #-----------------------------------------------
6127             #-----------------------------------------------
6128              
6129             sub compare_popularity_results
6130             {
6131              
6132 84     84 1 123 my $actual_choice ;
6133             my $adjusted_choice ;
6134 0         0 my $sequence_position ;
6135 0         0 my $ranking_level ;
6136 0         0 my $ranking_level_official ;
6137 0         0 my $comparison_of_methods_table ;
6138 0         0 my $ranking_level_choice_specific_pairwise_score ;
6139 0         0 my $ranking_level_insertion_sort ;
6140 0         0 my $possible_text_insertion_sort_not_the_same ;
6141 0         0 my $possible_text_choice_specific_pairwise_score_not_the_same ;
6142              
6143 0         0 my @actual_choice_at_popularity_list_sequence_position ;
6144              
6145              
6146             #-----------------------------------------------
6147             # Sort the official ranking results into a list
6148             # that is used when listing choice rankings,
6149             # which means that within the same ranking,
6150             # a lower choice number appears before a higher
6151             # choice number.
6152              
6153 84         112 $sequence_position = 1 ;
6154 84         246 for ( $ranking_level = 0 ; $ranking_level <= $global_adjusted_choice_count ; $ranking_level ++ )
6155             {
6156 559         1182 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
6157             {
6158 3642         3919 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
6159 3642 100       10219 if ( $global_popularity_ranking_for_actual_choice[ $actual_choice ] == $ranking_level )
6160             {
6161 475         769 $actual_choice_at_popularity_list_sequence_position[ $sequence_position ] = $actual_choice ;
6162 475         535 $global_log_info_choice_at_position[ $sequence_position ] = $actual_choice ;
6163 475         1123 $sequence_position ++ ;
6164             }
6165             }
6166             }
6167              
6168              
6169             #-----------------------------------------------
6170             # Log a display of the tally numbers in
6171             # an array version.
6172              
6173 84 50       179 if ( $global_logging_info == $global_true )
6174             {
6175 84         159 print LOGOUT "[compare pop results, ordered pairwise counts:]\n" ;
6176 84         197 &internal_view_matrix( ) ;
6177             }
6178              
6179              
6180             #-----------------------------------------------
6181             # Convert the tally numbers into percentages,
6182             # and display those values.
6183              
6184 84 50       255 if ( $global_logging_info == $global_true )
6185             {
6186 84         181 print LOGOUT "[compare pop results, total vote count is " . $global_current_total_vote_count . "]\n" ;
6187 84         115 $global_scale_for_logged_pairwise_counts = 100 / $global_current_total_vote_count ;
6188 84         434 print LOGOUT "[compare pop results, pairwise counts as percent numbers (if only scaled by total votes):]\n" ;
6189 84         154 &internal_view_matrix( ) ;
6190 84         160 $global_scale_for_logged_pairwise_counts = 1.0 ;
6191             }
6192              
6193              
6194             #-----------------------------------------------
6195             # As a check, compare the results of the
6196             # different ranking calculations.
6197             # Sort the results by popularity.
6198              
6199 84 100       258 if ( not( defined( $global_comparison_count ) ) )
6200             {
6201 1         2 $global_comparison_count = 0 ;
6202             }
6203 84         136 $global_comparison_count ++ ;
6204 84 100       210 if ( not( defined( $global_not_same_count ) ) )
6205             {
6206 1         14 $global_not_same_count = 0 ;
6207             }
6208 84         128 $possible_text_insertion_sort_not_the_same = "InsSrt same" ;
6209 84         120 $possible_text_choice_specific_pairwise_score_not_the_same = "CSPS same" ;
6210 84         309 $comparison_of_methods_table = "[compare pop results, case " . $global_case_number . " , question " . $global_question_number . " , rank type = " . $global_ranking_type_being_calculated . "]\n" ;
6211 84         141 $comparison_of_methods_table .= "[compare pop results, columns: official, insertion, estimated]\n" ;
6212 84         236 for ( $sequence_position = 1 ; $sequence_position <= $global_adjusted_choice_count ; $sequence_position ++ )
6213             {
6214 475         573 $actual_choice = $actual_choice_at_popularity_list_sequence_position[ $sequence_position ] ;
6215 475         571 $adjusted_choice = $global_adjusted_choice_for_actual_choice[ $actual_choice ] ;
6216 475         503 $ranking_level_official = $global_popularity_ranking_for_actual_choice[ $actual_choice ] ;
6217 475         697 $ranking_level_choice_specific_pairwise_score = $global_choice_score_popularity_rank_for_actual_choice[ $actual_choice ] ;
6218 475         511 $ranking_level_insertion_sort = $global_insertion_sort_popularity_rank_for_actual_choice[ $actual_choice ] ;
6219 475         1127 $comparison_of_methods_table .= "[choice " . sprintf( "%2d" , $actual_choice ) . " at levels " . $ranking_level_official . " , " . $ranking_level_insertion_sort . " , " . $ranking_level_choice_specific_pairwise_score . "]" ;
6220 475 50       1046 if ( $ranking_level_official != $ranking_level_insertion_sort )
6221             {
6222 0         0 $possible_text_insertion_sort_not_the_same = "InsSrt NOT same" ;
6223 0         0 $comparison_of_methods_table .= " ****** " ;
6224             }
6225 475 100       889 if ( $ranking_level_official != $ranking_level_choice_specific_pairwise_score )
6226             {
6227 225         313 $possible_text_choice_specific_pairwise_score_not_the_same = "CSPS NOT same" ;
6228 225         270 $comparison_of_methods_table .= " ------ " ;
6229             }
6230 475         1040 $comparison_of_methods_table .= "\n" ;
6231             }
6232 84 50       259 if ( $possible_text_insertion_sort_not_the_same eq "InsSrt NOT same" )
6233             {
6234 0         0 $global_not_same_count ++ ;
6235             }
6236 84         252 $comparison_of_methods_table .= "[" . $possible_text_insertion_sort_not_the_same . "][" . $possible_text_choice_specific_pairwise_score_not_the_same . "][case " . $global_case_number . " question " . $global_question_number . "]\n\n" ;
6237 84 50       212 if ( $global_logging_info == $global_true ) { print LOGOUT $comparison_of_methods_table . "\n" } ;
  84         573  
6238              
6239              
6240             #-----------------------------------------------
6241             # Display a count of how many rankings have
6242             # been done.
6243              
6244 84         128 $global_count_of_popularity_rankings ++ ;
6245 84 50       210 if ( $global_logging_info == $global_true ) { print LOGOUT "[count of popularity rankings: " . $global_count_of_popularity_rankings . "]\n" } ;
  84         182  
6246              
6247              
6248             #-----------------------------------------------
6249             # End of subroutine.
6250              
6251 84 50       187 if ( $global_logging_info == $global_true ) { print LOGOUT "[compare pop results, exiting subroutine]\n" } ;
  84         131  
6252 84         204 return 1 ;
6253              
6254             }
6255              
6256              
6257              
6258              
6259             =head2 do_full_initialization
6260              
6261             (Not exported, for internal use only.)
6262              
6263             Initializes all the global values and constants.
6264             It is always done at the beginning of executing
6265             this module. It is also executed if a new
6266             (second or later) set of cases is calculated.
6267              
6268             =cut
6269              
6270             #-----------------------------------------------
6271             #-----------------------------------------------
6272             # do_full_initialization
6273             #-----------------------------------------------
6274             #-----------------------------------------------
6275              
6276             sub do_full_initialization
6277             {
6278              
6279              
6280             #-----------------------------------------------
6281             # Define true and false constants.
6282              
6283 17     17 1 31 $global_true = 1 ;
6284 17         28 $global_false = 0 ;
6285              
6286              
6287             #-----------------------------------------------
6288             # Resetting logging flag.
6289              
6290 17         29 $global_logging_info = $global_true ;
6291              
6292              
6293             #-----------------------------------------------
6294             # Define constants.
6295              
6296 17         37 $global_warning_end = "\n-----\n\n" ;
6297              
6298              
6299             #-----------------------------------------------
6300             # Specify defaults.
6301              
6302 17         25 $global_default_representation_levels_requested = 6 ;
6303              
6304              
6305             #-----------------------------------------------
6306             # Set limits.
6307              
6308 17         25 $global_limit_on_popularity_rank_levels = 20 ;
6309 17         39 $global_limit_on_representation_rank_levels = 6 ;
6310 17         24 $global_maximum_case_number = 9999 ;
6311 17         28 $global_maximum_question_number = 99 ;
6312 17         22 $global_maximum_choice_number = 99 ;
6313 17         28 $global_max_array_length = 5000000 ;
6314 17         25 $global_maximum_twice_highest_possible_score = 999999 ;
6315              
6316              
6317             #-----------------------------------------------
6318             # Request that the output file embed negative
6319             # code numbers into text strings so that the
6320             # Vote-Info-Split-Join (VISJ) framework can
6321             # easily combine these results with text that
6322             # is extracted from EML and XML data (without
6323             # requiring a separate script/program to
6324             # convert negative numbers into Dashrep
6325             # phrases).
6326              
6327 17         28 $global_true_or_false_request_dashrep_phrases_in_output = $global_true ;
6328              
6329              
6330             #-----------------------------------------------
6331             # Initialize the "always" versions of the
6332             # requests for specified results.
6333              
6334 17         23 $global_true_or_false_always_request_only_plurality_results = $global_false ;
6335 17         25 $global_true_or_false_always_request_no_pairwise_counts = $global_false ;
6336 17         20 $global_true_or_false_always_request_votefair_representation_rank = $global_false ;
6337 17         25 $global_true_or_false_always_request_votefair_party_rank = $global_false ;
6338 17         22 $global_true_or_false_always_request_dashrep_phrases_in_output = $global_false ;
6339              
6340              
6341             #-----------------------------------------------
6342             # Initialization of zero and empty values.
6343              
6344 17         28 $global_length_of_vote_info_list = 0 ;
6345 17         20 $global_input_pointer_start_next_case = 0 ;
6346 17         30 $global_pointer_to_output_results = 0 ;
6347 17         24 $global_case_number = 0 ;
6348 17         19 $global_question_number = 0 ;
6349 17         28 $global_choice_number = 0 ;
6350 17         20 $global_ballot_info_repeat_count = 0 ;
6351 17         22 $global_current_total_vote_count = 0 ;
6352              
6353 17         28 $global_output_warning_message = "" ;
6354 17         29 $global_possible_error_message = "" ;
6355 17         30 $global_output_warning_messages_case_or_question_specific = "" ;
6356 17         28 $global_case_specific_warning_begin = "" ;
6357 17         24 $global_question_specific_warning_begin = "" ;
6358              
6359              
6360             #-----------------------------------------------
6361             # Clear the logged info flag only if it has not
6362             # yet been initialized.
6363              
6364 17 50       44 if ( not( defined( $global_logging_info ) ) )
6365             {
6366 0         0 $global_logging_info = $global_false ;
6367             }
6368              
6369              
6370             #-----------------------------------------------
6371             # Clear all the global values, except the ones
6372             # that are constants.
6373              
6374 17         25 $global_input_pointer_start_next_case = 0 ;
6375 17         24 $global_pointer_to_current_ballot = 0 ;
6376 17         25 $global_length_of_vote_info_list = 0 ;
6377 17         21 $global_pointer_to_output_results = 0 ;
6378 17         25 $global_length_of_result_info_list = 0 ;
6379 17         23 $global_case_number = 0 ;
6380 17         38 $global_previous_case_number = 0 ;
6381 17         19 $global_question_number = 0 ;
6382 17         40 $global_ballot_info_repeat_count = 0 ;
6383 17         17 $global_current_total_vote_count = 0 ;
6384 17         22 $global_ballot_influence_amount = 0 ;
6385 17         26 $global_choice_number = 0 ;
6386 17         23 $global_adjusted_choice_number = 0 ;
6387 17         25 $global_adjusted_choice_count = 0 ;
6388 17         22 $global_full_choice_count = 0 ;
6389 17         28 $global_pair_counter_maximum = 0 ;
6390 17         23 $global_question_count = 0 ;
6391 17         24 $global_choice_count_at_top_popularity_ranking_level = 0 ;
6392 17         20 $global_choice_count_at_full_top_popularity_ranking_level = 0 ;
6393 17         25 $global_choice_count_at_full_second_representation_level = 0 ;
6394 17         22 $global_representation_levels_requested = 0 ;
6395 17         23 $global_number_of_questions_in_current_case = 0 ;
6396 17         31 $global_first_most_popular_actual_choice = 0 ;
6397 17         19 $global_second_most_representative_actual_choice = 0 ;
6398 17         18 $global_actual_choice_at_top_of_full_popularity_ranking = 0 ;
6399 17         20 $global_actual_choice_at_second_representation_ranking = 0 ;
6400 17         29 $global_ranking_type_being_calculated = 0 ;
6401              
6402 17         30 $global_combined_case_number_and_question_number = "" ;
6403 17         28 $global_combined_case_number_and_question_number_and_choice_number = "" ;
6404 17         24 $global_pairwise_matrix_text = "" ;
6405 17         22 $global_case_specific_warning_begin = "" ;
6406 17         21 $global_question_specific_warning_begin = "" ;
6407              
6408 17         18 $global_true_or_false_tally_table_created = $global_false ;
6409              
6410 17         116 @global_vote_info_list = ( ) ;
6411 17         141 @global_output_results = ( ) ;
6412 17         44 @global_plurality_count_for_actual_choice = ( ) ;
6413 17         37 @global_popularity_ranking_for_actual_choice = ( ) ;
6414 17         29 @global_full_popularity_ranking_for_actual_choice = ( ) ;
6415 17         45 @global_representation_ranking_for_actual_choice = ( ) ;
6416 17         30 @global_full_representation_ranking_for_actual_choice = ( ) ;
6417 17         33 @global_party_ranking_for_actual_choice = ( ) ;
6418 17         29 @global_question_count_for_case = ( ) ;
6419 17         36 @global_true_or_false_ignore_case = ( ) ;
6420 17         42 @global_choice_count_for_case_and_question = ( ) ;
6421 17         35 @global_adjusted_choice_for_actual_choice = ( ) ;
6422 17         28 @global_actual_choice_for_adjusted_choice = ( ) ;
6423 17         39 @global_adjusted_first_choice_number_in_pair = ( ) ;
6424 17         33 @global_adjusted_second_choice_number_in_pair = ( ) ;
6425 17         30 @global_using_choice = ( ) ;
6426 17         74 @global_tally_first_over_second_in_pair = ( ) ;
6427 17         65 @global_tally_second_over_first_in_pair = ( ) ;
6428 17         35 @global_tally_first_equal_second_in_pair = ( ) ;
6429 17         44 @global_ballot_preference_for_choice = ( ) ;
6430 17         36 @global_adjusted_ranking_for_adjusted_choice_bottom_up_version = ( ) ;
6431 17         36 @global_adjusted_ranking_for_adjusted_choice_top_down_version = ( ) ;
6432 17         29 @global_pair_counter_offset_for_first_adjusted_choice = ( ) ;
6433 17         28 @global_log_info_choice_at_position = ( ) ;
6434              
6435              
6436             #-----------------------------------------------
6437             # If the begin-module actions have not yet
6438             # been done, begin to do them.
6439              
6440 17 100       51 if ( $global_begin_module_actions_done == $global_false )
6441             {
6442              
6443              
6444             #-----------------------------------------------
6445             # Specify the name of an extra output file
6446             # that contains a log of actions for the
6447             # purpose of debugging (or capturing
6448             # intermediate calculations).
6449              
6450 1         2 $global_log_filename = "output_votefair_debug_info.txt" ;
6451              
6452              
6453             #-----------------------------------------------
6454             # Open the file for writing log info.
6455              
6456 1         3790 open ( LOGOUT , ">" . $global_log_filename ) ;
6457              
6458              
6459             #-----------------------------------------------
6460             # Specify the name of an extra output file
6461             # that associates negative code numbers with
6462             # VISJ hyphenated phrases.
6463              
6464 1         4 $global_code_associations_filename = "output_from_vote_calc_sw_visj_codes.txt" ;
6465              
6466              
6467             #-----------------------------------------------
6468             # Open the file for writing the code-association
6469             # information.
6470              
6471 1         75 open ( CODEFILE , ">" . $global_code_associations_filename ) ;
6472              
6473              
6474             #-----------------------------------------------
6475             # Write definitions of the numeric codes that
6476             # are used for both input and output.
6477              
6478 1         5 &write_numeric_code_definitions( ) ;
6479              
6480              
6481             #-----------------------------------------------
6482             # Specify the name of an extra output file
6483             # that can contain an error message that will
6484             # be used by the VISJ code.
6485              
6486 1         52 $global_error_message_filename = "output_from_vote_calc_sw_visj_possible_error_message.txt" ;
6487              
6488              
6489             #-----------------------------------------------
6490             # Finish skipping over the actions that are
6491             # only done once.
6492              
6493             }
6494              
6495              
6496             #-----------------------------------------------
6497             # Indicate the the begin-module actions, and the
6498             # initializations, have been done.
6499              
6500 17         30 $global_begin_module_actions_done = $global_true ;
6501 17         26 $global_intitialization_done = $global_true ;
6502 17 50       43 if ( $global_logging_info == $global_true ) { print LOGOUT "[full initialization done]\n" } ;
  17         53  
6503              
6504              
6505             #-----------------------------------------------
6506             # End of initialization.
6507              
6508             }
6509              
6510              
6511              
6512              
6513             =head2 write_numeric_code_definitions
6514              
6515             (Not exported, for internal use only.)
6516              
6517             Write to an output file Dashrep definitions that
6518             associate negative code numbers -- that are used
6519             for input data and output results -- with
6520             text-based names for those values.
6521              
6522             =cut
6523              
6524             #-----------------------------------------------
6525             #-----------------------------------------------
6526             # write_numeric_code_definitions
6527             #-----------------------------------------------
6528             #-----------------------------------------------
6529              
6530             sub write_numeric_code_definitions
6531             {
6532              
6533 1     1 1 2 my $phrase_name ;
6534             my $next_code ;
6535 0         0 my $heading_text ;
6536 0         0 my $heading_begin ;
6537 0         0 my $heading_end ;
6538 0         0 my $end_definition ;
6539 0         0 my $text_inverse_part_1 ;
6540 0         0 my $text_inverse_part_2 ;
6541 0         0 my $letters ;
6542              
6543              
6544             #-----------------------------------------------
6545             # Write to a separate file the Dashrep-language
6546             # definitions that associate numeric codes
6547             # (negative numbers) with Dashrep hyphenated
6548             # phrases.
6549             # These codes are used for both the (input)
6550             # ballot information and the (output) results.
6551             # Also associate a unique variable name with
6552             # each code -- for use within this module.
6553              
6554 1         2 $heading_begin = "*------------------------------------------------------------\n" ;
6555 1         2 $heading_end = "\n------------------------------------------------------------*\n\n" ;
6556 1         3 $end_definition = "\n-----\n\n\n" ;
6557 1         1 $text_inverse_part_1 = "voteinfo-inverse-" ;
6558 1         3 $text_inverse_part_2 = "-code" . ":\n" . "output-" ;
6559              
6560 1         17 print CODEFILE "*----- Dashrep language -- phrase definitions -----*\n\n\n" ;
6561 1         2 print CODEFILE "*------------------------------------------------------------\n" ;
6562 1         3 print CODEFILE "See www.Dashrep.org for details about the Dashrep language.\n" ;
6563 1         2 print CODEFILE "------------------------------------------------------------*\n\n\n" ;
6564 1         2 print CODEFILE "*------------------------------------------------------------\n" ;
6565 1         7 print CODEFILE "Vote-Info-Split-Join, code-number associations.\n" ;
6566 1         2 print CODEFILE "------------------------------------------------------------*\n\n\n" ;
6567 1         2 print CODEFILE "*------------------------------------------------------------\n" ;
6568 1         2 print CODEFILE "\n" ;
6569 1         3 print CODEFILE " IMPORTANT! \n" ;
6570 1         2 print CODEFILE "\n" ;
6571 1         2 print CODEFILE "This file is generated by the vote-counting software,\n" ;
6572 1         2 print CODEFILE "so do not edit this file! Instead, edit the software that\n" ;
6573 1         2 print CODEFILE "generates this file.\n" ;
6574 1         2 print CODEFILE "------------------------------------------------------------*\n\n\n" ;
6575 1         2 print CODEFILE "dashrep-definitions-begin\n\n" ;
6576 1         2 print CODEFILE "*------------------------------------------------------------\n" ;
6577 1         3 print CODEFILE "Begin Dashrep definitions\n" ;
6578 1         2 print CODEFILE "------------------------------------------------------------*\n\n\n\n\n\n\n" ;
6579              
6580 1         2 $next_code = -1 ;
6581 1         2 $heading_text = "Code that identifies the start of all cases" ;
6582 1         7 $global_voteinfo_code_for_start_of_all_cases = $next_code ;
6583 1         2 $phrase_name = "voteinfo-code-for-start-of-all-cases" ;
6584 1         10 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6585 1         3 $letters = "startallcases" ;
6586 1         4 $global_code_number_for_letters{ $letters } = $next_code ;
6587              
6588 1         2 $next_code -- ;
6589 1         2 $heading_text = "Code that identifies the end of all cases" ;
6590 1         3 $global_voteinfo_code_for_end_of_all_cases = $next_code ;
6591 1         2 $phrase_name = "voteinfo-code-for-end-of-all-cases" ;
6592 1         7 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6593 1         2 $letters = "endallcases" ;
6594 1         2 $global_code_number_for_letters{ $letters } = $next_code ;
6595              
6596 1         3 $next_code -- ;
6597 1         1 $heading_text = "Code that identifies that the next number is a case number" ;
6598 1         2 $global_voteinfo_code_for_case_number = $next_code ;
6599 1         3 $phrase_name = "voteinfo-code-for-case-number" ;
6600 1         12 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6601 1         3 $letters = "case" ;
6602 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6603              
6604 1         2 $next_code -- ;
6605 1         2 $heading_text = "Code that identifies that the next number is a question number" ;
6606 1         3 $global_voteinfo_code_for_question_number = $next_code ;
6607 1         2 $phrase_name = "voteinfo-code-for-question-number" ;
6608 1         6 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6609 1         3 $letters = "q" ;
6610 1         2 $global_code_number_for_letters{ $letters } = $next_code ;
6611              
6612 1         2 $next_code -- ;
6613 1         1 $heading_text = "Code that indicates the total number of ballots" ;
6614 1         2 $global_voteinfo_code_for_total_ballot_count = $next_code ;
6615 1         2 $phrase_name = "voteinfo-code-for-total-ballot-count" ;
6616 1         5 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6617 1         3 $letters = "votes" ;
6618 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6619              
6620 1         1 $next_code -- ;
6621 1         9 $heading_text = "Code that identifies that the next number is the choice count for the current question" ;
6622 1         2 $global_voteinfo_code_for_number_of_choices = $next_code ;
6623 1         1 $phrase_name = "voteinfo-code-for-number-of-choices" ;
6624 1         6 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6625 1         3 $letters = "choices" ;
6626 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6627              
6628 1         2 $next_code -- ;
6629 1         2 $heading_text = "Code that identifies the beginning of the ballot information for the current case" ;
6630 1         3 $global_voteinfo_code_for_start_of_all_vote_info = $next_code ;
6631 1         2 $phrase_name = "voteinfo-code-for-start-of-all-vote-info" ;
6632 1         11 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6633 1         2 $letters = "startcase" ;
6634 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6635              
6636 1         2 $next_code -- ;
6637 1         2 $heading_text = "Code that identifies the end of the ballot information for the current case" ;
6638 1         2 $global_voteinfo_code_for_end_of_all_vote_info = $next_code ;
6639 1         2 $phrase_name = "voteinfo-code-for-end-of-all-vote-info" ;
6640 1         6 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6641 1         3 $letters = "endcase" ;
6642 1         4 $global_code_number_for_letters{ $letters } = $next_code ;
6643              
6644 1         2 $next_code -- ;
6645 1         2 $heading_text = "Code that identifies the beginning of information for the next ballot" ;
6646 1         1 $global_voteinfo_code_for_start_of_ballot = $next_code ;
6647 1         2 $phrase_name = "voteinfo-code-for-start-of-ballot" ;
6648 1         6 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6649 1         2 $letters = "bal" ;
6650 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6651              
6652 1         2 $next_code -- ;
6653 1         3 $heading_text = "Code that identifies the end of the current ballot" ;
6654 1         2 $global_voteinfo_code_for_end_of_ballot = $next_code ;
6655 1         2 $phrase_name = "voteinfo-code-for-end-of-ballot" ;
6656 1         7 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6657 1         2 $letters = "b" ;
6658 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6659              
6660 1         2 $next_code -- ;
6661 1         7 $heading_text = "Code that identifies that the next number indicates how many ballots have the same preferences\n(to allow compression for repeated ballot preferences)" ;
6662 1         2 $global_voteinfo_code_for_ballot_count = $next_code ;
6663 1         2 $phrase_name = "voteinfo-code-for-ballot-count" ;
6664 1         7 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6665 1         2 $letters = "x" ;
6666 1         2 $global_code_number_for_letters{ $letters } = $next_code ;
6667              
6668 1         2 $next_code -- ;
6669 1         30 $heading_text = "Code that identifies that the next number is a preference level (that applies to choice numbers that follow)" ;
6670 1         3 $global_voteinfo_code_for_preference_level = $next_code ;
6671 1         3 $phrase_name = "voteinfo-code-for-preference-level" ;
6672 1         12 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6673 1         2 $letters = "pref" ;
6674 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6675              
6676 1         2 $next_code -- ;
6677 1         2 $heading_text = "Code that identifies that the next number is a choice number" ;
6678 1         2 $global_voteinfo_code_for_choice = $next_code ;
6679 1         2 $phrase_name = "voteinfo-code-for-choice" ;
6680 1         7 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6681 1         2 $letters = "ch" ;
6682 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6683              
6684 1         2 $next_code -- ;
6685 1         2 $heading_text = "Code that identifies that the previous choice and the next choice are at the same preference level" ;
6686 1         2 $global_voteinfo_code_for_tie = $next_code ;
6687 1         2 $phrase_name = "voteinfo-code-for-tie" ;
6688 1         151 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6689 1         3 $letters = "tie" ;
6690 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6691              
6692 1         2 $next_code -- ;
6693 1         2 $heading_text = "Code that identifies the beginning of VoteFair popularity ranking sequence-style results" ;
6694 1         3 $global_voteinfo_code_for_start_of_votefair_popularity_ranking_sequence_results = $next_code ;
6695 1         1 $phrase_name = "voteinfo-code-for-start-of-votefair-popularity-ranking-sequence-results" ;
6696 1         7 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . "ignore-begin" . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6697 1         2 $letters = "popularity-sequence" ;
6698 1         4 $global_code_number_for_letters{ $letters } = $next_code ;
6699              
6700 1         1 $next_code -- ;
6701 1         2 $heading_text = "Code that identifies the end of VoteFair popularity ranking sequence-style results" ;
6702 1         2 $global_voteinfo_code_for_end_of_votefair_popularity_ranking_sequence_results = $next_code ;
6703 1         2 $phrase_name = "voteinfo-code-for-end-of-votefair-popularity-ranking-sequence-results" ;
6704 1         7 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . "ignore-end" . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6705 1         2 $letters = "end-pop-seq" ;
6706 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6707              
6708 1         2 $next_code -- ;
6709 1         2 $heading_text = "Code that identifies the beginning of VoteFair popularity levels-style ranking results" ;
6710 1         2 $global_voteinfo_code_for_start_of_votefair_popularity_ranking_levels_results = $next_code ;
6711 1         1502 $phrase_name = "voteinfo-code-for-start-of-votefair-popularity-ranking-levels-results" ;
6712 1         13 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . "ignore-begin" . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6713 1         3 $letters = "popularity-levels" ;
6714 1         18 $global_code_number_for_letters{ $letters } = $next_code ;
6715              
6716 1         2 $next_code -- ;
6717 1         2 $heading_text = "Code that identifies the end of VoteFair popularity levels-style ranking results" ;
6718 1         3 $global_voteinfo_code_for_end_of_votefair_popularity_ranking_levels_results = $next_code ;
6719 1         2 $phrase_name = "voteinfo-code-for-end-of-votefair-popularity-ranking-levels-results" ;
6720 1         7 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . "ignore-end" . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6721 1         2 $letters = "end-pop-levels" ;
6722 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6723              
6724 1         1 $next_code -- ;
6725 1         2 $heading_text = "Code that identifies the beginning of VoteFair representation ranking sequence results" ;
6726 1         3 $global_voteinfo_code_for_start_of_votefair_representation_ranking_sequence_results = $next_code ;
6727 1         2 $phrase_name = "voteinfo-code-for-start-of-votefair-representation-ranking-sequence-results" ;
6728 1         7 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . "ignore-begin" . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6729 1         2 $letters = "rep-seq" ;
6730 1         2 $global_code_number_for_letters{ $letters } = $next_code ;
6731              
6732 1         2 $next_code -- ;
6733 1         2 $heading_text = "Code that identifies the end of VoteFair representation ranking sequence results" ;
6734 1         2 $global_voteinfo_code_for_end_of_votefair_representation_ranking_sequence_results = $next_code ;
6735 1         2 $phrase_name = "voteinfo-code-for-end-of-votefair-representation-ranking-sequence-results" ;
6736 1         6 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . "ignore-end" . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6737 1         2 $letters = "end-rep-seq" ;
6738 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6739              
6740 1         2 $next_code -- ;
6741 1         1 $heading_text = "Code that identifies the beginning of VoteFair representation ranking levels results" ;
6742 1         2 $global_voteinfo_code_for_start_of_votefair_representation_ranking_levels_results = $next_code ;
6743 1         2 $phrase_name = "voteinfo-code-for-start-of-votefair-representation-ranking-levels-results" ;
6744 1         80 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . "ignore-begin" . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6745 1         3 $letters = "rep-levels" ;
6746 1         2 $global_code_number_for_letters{ $letters } = $next_code ;
6747              
6748 1         2 $next_code -- ;
6749 1         1 $heading_text = "Code that identifies the end of VoteFair representation ranking levels results" ;
6750 1         3 $global_voteinfo_code_for_end_of_votefair_representation_ranking_levels_results = $next_code ;
6751 1         2 $phrase_name = "voteinfo-code-for-end-of-votefair-representation-ranking-levels-results" ;
6752 1         7 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . "ignore-end" . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6753 1         1 $letters = "end-rep-levels" ;
6754 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6755              
6756 1         2 $next_code -- ;
6757 1         2 $heading_text = "Code that identifies the beginning of VoteFair party ranking sequence results" ;
6758 1         2 $global_voteinfo_code_for_start_of_votefair_party_ranking_sequence_results = $next_code ;
6759 1         2 $phrase_name = "voteinfo-code-for-start-of-votefair-party-ranking-sequence-results" ;
6760 1         6 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . "ignore-begin" . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6761 1         2 $letters = "party-seq" ;
6762 1         8 $global_code_number_for_letters{ $letters } = $next_code ;
6763              
6764 1         2 $next_code -- ;
6765 1         2 $heading_text = "Code that identifies the end of VoteFair party ranking sequence results" ;
6766 1         2 $global_voteinfo_code_for_end_of_votefair_party_ranking_sequence_results = $next_code ;
6767 1         2 $phrase_name = "voteinfo-code-for-end-of-votefair-party-ranking-sequence-results" ;
6768 1         11 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . "ignore-end" . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6769 1         3 $letters = "end-party-seq" ;
6770 1         2 $global_code_number_for_letters{ $letters } = $next_code ;
6771              
6772 1         2 $next_code -- ;
6773 1         1 $heading_text = "Code that identifies the beginning of VoteFair party ranking levels results" ;
6774 1         2 $global_voteinfo_code_for_start_of_votefair_party_ranking_levels_results = $next_code ;
6775 1         3 $phrase_name = "voteinfo-code-for-start-of-votefair-party-ranking-levels-results" ;
6776 1         6 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . "ignore-begin" . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6777 1         2 $letters = "party-levels" ;
6778 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6779              
6780 1         2 $next_code -- ;
6781 1         2 $heading_text = "Code that identifies the end of VoteFair party ranking levels results" ;
6782 1         1 $global_voteinfo_code_for_end_of_votefair_party_ranking_levels_results = $next_code ;
6783 1         2 $phrase_name = "voteinfo-code-for-end-of-votefair-party-ranking-levels-results" ;
6784 1         6 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . "ignore-end" . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6785 1         3 $letters = "end-party-levels" ;
6786 1         2 $global_code_number_for_letters{ $letters } = $next_code ;
6787              
6788 1         2 $next_code -- ;
6789 1         1 $heading_text = "Code that identifies the ranking level (in the output results)" ;
6790 1         2 $global_voteinfo_code_for_ranking_level = $next_code ;
6791 1         2 $phrase_name = "voteinfo-code-for-ranking-level" ;
6792 1         6 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6793 1         2 $letters = "level" ;
6794 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6795              
6796 1         2 $next_code -- ;
6797 1         1 $heading_text = "Code that identifies the next lower level of ranking (in the output results)" ;
6798 1         8 $global_voteinfo_code_for_next_ranking_level = $next_code ;
6799 1         2 $phrase_name = "voteinfo-code-for-next-ranking-level" ;
6800 1         7 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6801 1         1 $letters = "next-level" ;
6802 1         9 $global_code_number_for_letters{ $letters } = $next_code ;
6803              
6804 1         2 $next_code -- ;
6805 1         1 $heading_text = "Code that identifies that the sequence results stop here, without all choices being ranked" ;
6806 1         2 $global_voteinfo_code_for_early_end_of_ranking = $next_code ;
6807 1         2 $phrase_name = "voteinfo-code-for-early-end-of-ranking" ;
6808 1         5 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6809 1         2 $letters = "end-seq-early" ;
6810 1         2 $global_code_number_for_letters{ $letters } = $next_code ;
6811              
6812 1         1 $next_code -- ;
6813 1         2 $heading_text = "Code that identifies the beginning of tally-table counts" ;
6814 1         2 $global_voteinfo_code_for_start_of_tally_table_results = $next_code ;
6815 1         2 $phrase_name = "voteinfo-code-for-start-of-tally-table-results" ;
6816 1         6 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . "ignore-begin" . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6817 1         1 $letters = "tallies" ;
6818 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6819              
6820 1         1 $next_code -- ;
6821 1         2 $heading_text = "Code that identifies the end of tally-table counts" ;
6822 1         2 $global_voteinfo_code_for_end_of_tally_table_results = $next_code ;
6823 1         2 $phrase_name = "voteinfo-code-for-end-of-tally-table-results" ;
6824 1         10 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . "ignore-end" . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6825 1         1 $letters = "end-tallies" ;
6826 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6827              
6828 1         1 $next_code -- ;
6829 1         1 $heading_text = "Code that identifies that the next number is the first choice number in a pair (in tally-table results)" ;
6830 1         2 $global_voteinfo_code_for_first_choice = $next_code ;
6831 1         3 $phrase_name = "voteinfo-code-for-first-choice" ;
6832 1         5 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6833 1         2 $letters = "ch1" ;
6834 1         22 $global_code_number_for_letters{ $letters } = $next_code ;
6835              
6836 1         3 $next_code -- ;
6837 1         1 $heading_text = "Code that identifies that the next number is the second choice number in a pair (in tally-table results)" ;
6838 1         3 $global_voteinfo_code_for_second_choice = $next_code ;
6839 1         2 $phrase_name = "voteinfo-code-for-second-choice" ;
6840 1         6 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6841 1         2 $letters = "ch2" ;
6842 1         2 $global_code_number_for_letters{ $letters } = $next_code ;
6843              
6844 1         1 $next_code -- ;
6845 1         2 $heading_text = "Code that identifies that the next number indicates how many ballots rank the first choice over the second choice" ;
6846 1         2 $global_voteinfo_code_for_tally_first_over_second = $next_code ;
6847 1         2 $phrase_name = "voteinfo-code-for-tally-first-over-second" ;
6848 1         7 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6849 1         1 $letters = "1over2" ;
6850 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6851              
6852 1         3 $next_code -- ;
6853 1         2 $heading_text = "Code that identifies that the next number indicates how many ballots rank the second choice over the first choice" ;
6854 1         2 $global_voteinfo_code_for_tally_second_over_first = $next_code ;
6855 1         2 $phrase_name = "voteinfo-code-for-tally-second-over-first" ;
6856 1         6 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6857 1         2 $letters = "2over1" ;
6858 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6859              
6860 1         2 $next_code -- ;
6861 1         2 $heading_text = "Code that identifies the beginning of plurality results" ;
6862 1         3 $global_voteinfo_code_for_start_of_plurality_results = $next_code ;
6863 1         2 $phrase_name = "voteinfo-code-for-start-of-plurality-results" ;
6864 1         31 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . "ignore-begin" . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6865 1         4 $letters = "plurality" ;
6866 1         2 $global_code_number_for_letters{ $letters } = $next_code ;
6867              
6868 1         3 $next_code -- ;
6869 1         2 $heading_text = "Code that identifies the end of plurality results" ;
6870 1         2 $global_voteinfo_code_for_end_of_plurality_results = $next_code ;
6871 1         2 $phrase_name = "voteinfo-code-for-end-of-plurality-results" ;
6872 1         6 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . "ignore-end" . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6873 1         2 $letters = "end-plurality" ;
6874 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6875              
6876 1         2 $next_code -- ;
6877 1         1 $heading_text = "Code that identifies a plurality count (how many ballots rank the specified choice as their only first choice)" ;
6878 1         2 $global_voteinfo_code_for_plurality_count = $next_code ;
6879 1         2 $phrase_name = "voteinfo-code-for-plurality-count" ;
6880 1         6 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6881 1         2 $letters = "plur" ;
6882 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6883              
6884 1         2 $next_code -- ;
6885 1         2 $heading_text = "Code that indicates this case was skipped (the reason is explained in the warning)" ;
6886 1         2 $global_voteinfo_code_for_skip_case = $next_code ;
6887 1         2 $phrase_name = "voteinfo-code-for-skip-case" ;
6888 1         8 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6889 1         2 $letters = "case-skipped" ;
6890 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6891              
6892 1         2 $next_code -- ;
6893 1         34 $heading_text = "Code that indicates this question was skipped (the reason is explained in the warning)" ;
6894 1         3 $global_voteinfo_code_for_skip_question = $next_code ;
6895 1         2 $phrase_name = "voteinfo-code-for-skip-question" ;
6896 1         8 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6897 1         2 $letters = "question-skipped" ;
6898 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6899              
6900 1         2 $next_code -- ;
6901 1         2 $heading_text = "Code that requests VoteFair representation ranking results" ;
6902 1         3 $global_voteinfo_code_for_request_votefair_representation_rank = $next_code ;
6903 1         2 $phrase_name = "voteinfo-code-for-request-votefair-representation-rank" ;
6904 1         6 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6905 1         3 $letters = "request-rep" ;
6906 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6907              
6908 1         2 $next_code -- ;
6909 1         2 $heading_text = "Code that requests no VoteFair representation ranking results" ;
6910 1         2 $global_voteinfo_code_for_request_no_votefair_representation_rank = $next_code ;
6911 1         2 $phrase_name = "voteinfo-code-for-request-no-votefair-representation-rank" ;
6912 1         6 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6913 1         2 $letters = "request-no-rep" ;
6914 1         4 $global_code_number_for_letters{ $letters } = $next_code ;
6915              
6916 1         1 $next_code -- ;
6917 1         2 $heading_text = "Code that requests VoteFair party ranking results" ;
6918 1         3 $global_voteinfo_code_for_request_votefair_party_rank = $next_code ;
6919 1         2 $phrase_name = "voteinfo-code-for-request-votefair-party-rank" ;
6920 1         7 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6921 1         2 $letters = "request-party" ;
6922 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6923              
6924 1         1 $next_code -- ;
6925 1         3 $heading_text = "Code that requests no VoteFair party ranking results" ;
6926 1         2 $global_voteinfo_code_for_request_no_votefair_party_rank = $next_code ;
6927 1         2 $phrase_name = "voteinfo-code-for-request-no-votefair-party-rank" ;
6928 1         45 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6929 1         2 $letters = "request-no-party" ;
6930 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6931              
6932 1         3 $next_code -- ;
6933 1         2 $heading_text = "Code that requests only plurality results" ;
6934 1         2 $global_voteinfo_code_for_request_only_plurality_results = $next_code ;
6935 1         1 $phrase_name = "voteinfo-code-for-request-only-plurality-results" ;
6936 1         7 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6937 1         3 $letters = "request-plurality-only" ;
6938 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6939              
6940 1         1 $next_code -- ;
6941 1         2 $heading_text = "Code that requests pairwise counts" ;
6942 1         8 $global_voteinfo_code_for_request_pairwise_counts = $next_code ;
6943 1         25 $phrase_name = "voteinfo-code-for-request-pairwise-counts" ;
6944 1         7 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6945 1         2 $letters = "request-pairwise-counts" ;
6946 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6947              
6948 1         2 $next_code -- ;
6949 1         2 $heading_text = "Code that requests no pairwise counts" ;
6950 1         2 $global_voteinfo_code_for_request_no_pairwise_counts = $next_code ;
6951 1         2 $phrase_name = "voteinfo-code-for-request-no-pairwise-counts" ;
6952 1         8 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n" . $next_code . $end_definition . $text_inverse_part_1 . sprintf( "%d" , -( $next_code ) ) . $text_inverse_part_2 . $phrase_name . $end_definition ;
6953 1         2 $letters = "request-no-pairwise-counts" ;
6954 1         3 $global_code_number_for_letters{ $letters } = $next_code ;
6955              
6956 1         3 $heading_text = "Definition that initializes the error message" ;
6957 1         2 $phrase_name = "output-error-message" ;
6958 1         4 print CODEFILE $heading_begin . $heading_text . $heading_end . $phrase_name . ":\n-----\n\n\n" ;
6959              
6960 1         6 print CODEFILE "\n\n\n" . $heading_begin . "End of Dashrep definitions" . $heading_end . "dashrep-definitions-end" . "\n\n" ;
6961              
6962 1         34 close ( CODEFILE ) ;
6963              
6964              
6965             #-----------------------------------------------
6966             # End of subroutine.
6967              
6968             }
6969              
6970              
6971              
6972              
6973              
6974             =head2 check_vote_info_numbers
6975              
6976             (Not exported, for internal use only.)
6977              
6978             Checks the validity of the numbers in the vote-info
6979             list, and requests skipping any cases or questions
6980             that contain invalid data. Also, counts the
6981             number of questions in each case, and counts the
6982             choices in each question.
6983              
6984             =cut
6985              
6986             #-----------------------------------------------
6987             #-----------------------------------------------
6988             # check_vote_info_numbers
6989             #-----------------------------------------------
6990             #-----------------------------------------------
6991              
6992             sub check_vote_info_numbers
6993             {
6994              
6995 17     17 1 28 my $status_pair_just_handled ;
6996             my $current_vote_info_number ;
6997 0         0 my $previous_vote_info_number ;
6998 0         0 my $next_vote_info_number ;
6999 0         0 my $pointer_to_vote_info ;
7000 0         0 my $within_ballots ;
7001 0         0 my $choice_count_for_current_question ;
7002 0         0 my $count_of_choices_marked_for_current_question ;
7003              
7004 0         0 my @tally_uses_of_question_number ;
7005 0         0 my @tally_uses_of_choice_number ;
7006 0         0 my @tally_uses_of_question_and_choice_number ;
7007              
7008              
7009             #-----------------------------------------------
7010             # Initialization.
7011              
7012 17         33 $global_case_specific_warning_begin = "case-" . "0" . "-warning-message:\n" . "word-case-capitalized " . "0" ;
7013 17         28 @tally_uses_of_question_number = ( ) ;
7014 17         28 @tally_uses_of_choice_number = ( ) ;
7015              
7016              
7017             #-----------------------------------------------
7018             # In case the debug messages in this subroutine
7019             # are ignored, write the debug messages
7020             # collected so far.
7021              
7022 17 50       58 if ( $global_logging_info == $global_true ) { print LOGOUT "\n[about to start checking vote-info numbers]\n\n" } ;
  17         44  
7023              
7024              
7025             #-----------------------------------------------
7026             # If the list of numbers is empty, indicate an
7027             # error.
7028              
7029 17 50       47 if ( $global_length_of_vote_info_list < 2 )
7030             {
7031 0         0 return "Error: No data was supplied" ;
7032             }
7033              
7034              
7035             #-----------------------------------------------
7036             # Begin a loop that handles each vote-info
7037             # number in the list.
7038              
7039 17         25 $pointer_to_vote_info = 0 ;
7040 17         18 $current_vote_info_number = 0 ;
7041 17         22 $previous_vote_info_number = 0 ;
7042 17         21 $next_vote_info_number = 0 ;
7043 17         25 @tally_uses_of_question_number = ( ) ;
7044 17         26 @tally_uses_of_choice_number = ( ) ;
7045 17         32 @global_true_or_false_ignore_case = ( ) ;
7046 17         32 @global_question_count_for_case = ( ) ;
7047 17         27 @global_choice_count_for_case_and_question = ( ) ;
7048 17         23 $global_case_number = 0 ;
7049 17         31 $global_number_of_questions_in_current_case = 0 ;
7050 17         25 $status_pair_just_handled = $global_false ;
7051 17         23 $global_ballot_info_repeat_count = 0 ;
7052 17         20 $global_current_total_vote_count = 0 ;
7053 17 50       47 if ( $global_logging_info == $global_true ) { print LOGOUT "\n\n" } ;
  17         31  
7054 17 50       49 if ( $global_logging_info == $global_true ) { print LOGOUT "[input info list length = " . $global_length_of_vote_info_list . "]" } ;
  17         50  
7055 17 50       44 if ( $global_logging_info == $global_true ) { print LOGOUT "[begin checking vote info numbers]\n" } ;
  17         30  
7056 17         27 $global_case_specific_warning_begin = "" ;
7057 17         26 $global_question_specific_warning_begin = "" ;
7058 17         69 for ( $pointer_to_vote_info = 0 ; $pointer_to_vote_info <= $global_length_of_vote_info_list - 1 ; $pointer_to_vote_info ++ )
7059             {
7060              
7061              
7062             #-----------------------------------------------
7063             # If this vote-info number was preceded by a
7064             # code that already handled this vote-info
7065             # number, repeat the loop for the next vote-info
7066             # number.
7067              
7068 866 100       1565 if ( $status_pair_just_handled == $global_true )
7069             {
7070 213         227 $status_pair_just_handled = $global_false ;
7071 213         435 next ;
7072             }
7073 653         680 $status_pair_just_handled = $global_false ;
7074              
7075              
7076             #-----------------------------------------------
7077             # Get the current vote-info number, and adjacent
7078             # vote-info numbers.
7079              
7080 653         752 $current_vote_info_number = $global_vote_info_list[ $pointer_to_vote_info ] ;
7081             # if ( $global_logging_info == $global_true ) { print LOGOUT "[" . $current_vote_info_number . " is at " . $pointer_to_vote_info . "]" } ;
7082 653 100       1027 if ( $pointer_to_vote_info <= 0 )
7083             {
7084 17         25 $previous_vote_info_number = 0 ;
7085             } else
7086             {
7087 636         866 $previous_vote_info_number = $global_vote_info_list[ $pointer_to_vote_info - 1 ] ;
7088             }
7089 653 50       1060 if ( $pointer_to_vote_info + 1 > $global_length_of_vote_info_list )
7090             {
7091 0         0 $next_vote_info_number = 0 ;
7092             } else
7093             {
7094 653         884 $next_vote_info_number = $global_vote_info_list[ $pointer_to_vote_info + 1 ] ;
7095             }
7096              
7097              
7098             #-----------------------------------------------
7099             # Ignore a code value of zero.
7100              
7101 653 50       1296 if ( $current_vote_info_number == 0 )
7102             {
7103 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[ignoring zero value]" } ;
  0         0  
7104 0         0 next ;
7105             }
7106              
7107              
7108             #-----------------------------------------------
7109             # Handle the end of a case.
7110              
7111 653 100 100     3712 if ( ( $current_vote_info_number == $global_voteinfo_code_for_case_number ) || ( $current_vote_info_number == $global_voteinfo_code_for_end_of_all_cases ) || ( $current_vote_info_number == $global_voteinfo_code_for_end_of_all_vote_info ) )
      100        
7112             {
7113 40 100       132 if ( $global_case_number > 0 )
    50          
7114             {
7115 23 50       62 if ( $global_logging_info == $global_true ) { print LOGOUT "[case " . $global_case_number . " ending]" } ;
  23         47  
7116 23 50       65 if ( not( defined( $global_true_or_false_ignore_case[ $global_case_number ] ) ) )
7117             {
7118 0         0 $global_true_or_false_ignore_case[ $global_case_number ] = $global_false ;
7119             }
7120 23 50       55 if ( $global_true_or_false_ignore_case[ $global_case_number ] == $global_false )
7121             {
7122 23 50 33     140 if ( ( $global_number_of_questions_in_current_case < 1 ) || ( $global_question_count_for_case[ $global_case_number ] < 1 ) )
    100          
7123             {
7124 0         0 $global_true_or_false_ignore_case[ $global_case_number ] = $global_true ;
7125 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[case-contains-no-questions (case " . $global_case_number . ", new case starting at list position " . $pointer_to_vote_info . ")]" } ;
  0         0  
7126 0         0 $global_output_warning_messages_case_or_question_specific .= $global_case_specific_warning_begin . " words-contains-no-questions" . $global_warning_end ;
7127 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[ignoring case " . $global_case_number . "]" } ;
  0         0  
7128             } elsif ( $global_current_total_vote_count < 1 )
7129             {
7130 1         2 $global_true_or_false_ignore_case[ $global_case_number ] = $global_true ;
7131 1 50       5 if ( $global_logging_info == $global_true ) { print LOGOUT "[case-contains-no-ballots (case " . $global_case_number . ", new case starting at list position " . $pointer_to_vote_info . ")]" } ;
  1         5  
7132 1         4 $global_output_warning_messages_case_or_question_specific .= $global_case_specific_warning_begin . " words-contains-no-ballots" . $global_warning_end ;
7133 1 50       4 if ( $global_logging_info == $global_true ) { print LOGOUT "[ignoring case " . $global_case_number . "]" } ;
  1         4  
7134             } else
7135             {
7136 22         63 for ( $global_question_number = 1 ; $global_question_number <= $global_question_count_for_case[ $global_case_number ] ; $global_question_number ++ )
7137             {
7138 24 50       50 if ( $global_logging_info == $global_true ) { print LOGOUT "[question " . $global_question_number . " has " . $global_choice_count_for_case_and_question[ $global_case_number ][ $global_question_number ] . " choices]" } ;
  24         82  
7139 24 50       159 if ( not( defined( $global_choice_count_for_case_and_question[ $global_case_number ][ $global_question_number ] ) ) )
    100          
    50          
7140             {
7141 0         0 $global_true_or_false_ignore_case[ $global_case_number ] = $global_true ;
7142 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[choice-count-not-specified (undefined) (question " . $global_question_number . ")]" } ;
  0         0  
7143 0         0 $global_output_warning_messages_case_or_question_specific .= $global_case_specific_warning_begin . " does-not-specify-number-of-choices" . $global_warning_end ;
7144 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[ignoring case " . $global_case_number . "]" } ;
  0         0  
7145 0         0 last ;
7146             } elsif ( $global_choice_count_for_case_and_question[ $global_case_number ][ $global_question_number ] == 1 )
7147             {
7148 1         2 $global_true_or_false_ignore_case[ $global_case_number ] = $global_true ;
7149 1 50       5 if ( $global_logging_info == $global_true ) { print LOGOUT "[only-one-choice (question " . $global_question_number . ")]" } ;
  1         4  
7150 1         2 $global_output_warning_messages_case_or_question_specific .= $global_case_specific_warning_begin . " only-one-choice" . $global_warning_end ;
7151 1 50       5 if ( $global_logging_info == $global_true ) { print LOGOUT "[ignoring case " . $global_case_number . "]" } ;
  1         3  
7152 1         3 last ;
7153             } elsif ( $global_choice_count_for_case_and_question[ $global_case_number ][ $global_question_number ] < 1 )
7154             {
7155 0         0 $global_true_or_false_ignore_case[ $global_case_number ] = $global_true ;
7156 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[no-choices-found-for-question (case " . $global_case_number . ", question " . $global_question_number . ", end of all vote info at list position " . $pointer_to_vote_info . ")]" } ;
  0         0  
7157 0         0 $global_output_warning_messages_case_or_question_specific .= $global_question_specific_warning_begin . ", word-question " . $global_question_number . " has-no-choices" . $global_warning_end ;
7158 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[ignoring case " . $global_case_number . "]" } ;
  0         0  
7159 0         0 last ;
7160             }
7161             }
7162             }
7163 23 100       55 if ( $global_true_or_false_ignore_case[ $global_case_number ] == $global_false )
7164             {
7165 21 50       51 if ( $global_logging_info == $global_true ) { print LOGOUT "[case " . $global_case_number . " ending without errors]" } ;
  21         51  
7166 21 50       55 if ( $global_logging_info == $global_true ) { print LOGOUT "[total ballot count " . $global_current_total_vote_count . "]" } ;
  21         52  
7167             }
7168             }
7169             } elsif ( $current_vote_info_number != $global_voteinfo_code_for_case_number )
7170             {
7171 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[reached end of case or ballot info, but no case has been started]" } ;
  0         0  
7172 0         0 return "Error: Encountered case-specific vote-info number before first case started (input list position " . $pointer_to_vote_info . ")" ;
7173             }
7174 40         58 $global_question_number = 0 ;
7175             }
7176              
7177              
7178             #-----------------------------------------------
7179             # Handle the code for a case number.
7180              
7181 653 100       1565 if ( $current_vote_info_number == $global_voteinfo_code_for_case_number )
    50          
7182             {
7183 20         27 $global_previous_case_number = $global_case_number ;
7184 20         24 $global_case_number = $next_vote_info_number ;
7185 20         25 $status_pair_just_handled = $global_true ;
7186 20         66 $global_case_specific_warning_begin = "case-" . $global_case_number . "-warning-message:\n" . "word-case-capitalized " . $global_case_number ;
7187 20         27 $global_current_total_vote_count = 0 ;
7188 20 50       52 if ( $global_logging_info == $global_true ) { print LOGOUT "\n[case " . $global_case_number . "]\n\n" } ;
  20         60  
7189 20 50       52 if ( $global_case_number <= 0 )
7190             {
7191 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[error, first case number is " . $global_case_number . " instead of one]" } ;
  0         0  
7192 0         0 return "Error: First case number is not one" ;
7193             }
7194 20 50       117 if ( $global_case_number > $global_maximum_case_number )
7195             {
7196 0         0 $global_true_or_false_ignore_case[ $global_case_number ] = $global_true ;
7197 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[error-case-number-exceeds-limit (limit is " . $global_maximum_case_number . ", list position is " . $pointer_to_vote_info . ")]" } ;
  0         0  
7198 0         0 $global_output_warning_messages_case_or_question_specific .= $global_case_specific_warning_begin . " exceeds-limit-for-number-of-cases" . $global_warning_end ;
7199 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[ignoring case " . $global_case_number . "]" } ;
  0         0  
7200             }
7201 20 50       55 if ( $global_case_number != $global_previous_case_number + 1 )
7202             {
7203 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[error-case-number-is-not-sequential (case number " . $global_case_number . " instead of " . ( $global_previous_case_number + 1 ) . ")]" } ;
  0         0  
7204 0         0 return "Error: Case number is not sequential (case number " . $global_case_number . " instead of " . ( $global_previous_case_number + 1 ) . ")" ;
7205             }
7206 20         40 $global_question_count_for_case[ $global_case_number ] = 0 ;
7207 20         24 $global_question_number = 0 ;
7208 20         25 $global_current_total_vote_count = 0 ;
7209 20 50       39 if ( defined( $global_true_or_false_ignore_case[ $global_case_number ] ) )
7210             {
7211 0 0       0 if ( $global_true_or_false_ignore_case[ $global_case_number ] == $global_true )
7212             {
7213 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[ignoring case " . $global_case_number . " as previously requested]" } ;
  0         0  
7214             }
7215             } else
7216             {
7217 20         29 $global_true_or_false_ignore_case[ $global_case_number ] = $global_false ;
7218             }
7219 20         30 $global_number_of_questions_in_current_case = 0 ;
7220 20         34 @tally_uses_of_question_number = ( ) ;
7221 20         22 @tally_uses_of_question_and_choice_number = ( ) ;
7222 20         26 $within_ballots = $global_false ;
7223 20         46 $global_case_specific_warning_begin = "case-" . $global_case_number . "-warning-message:\n" . "word-case-capitalized " . $global_case_number ;
7224 20         64 next ;
7225              
7226              
7227             #-----------------------------------------------
7228             # If a case number is not defined, assume a
7229             # case number of one.
7230              
7231             } elsif ( not( defined( $global_case_number ) ) )
7232             {
7233 0         0 $global_case_number = 1 ;
7234 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[case number not yet encountered, so case number is assumed to be one]" } ;
  0         0  
7235             }
7236              
7237              
7238             #-----------------------------------------------
7239             # If the ignore-case flag for the current case
7240             # number has not yet been initialized, then
7241             # initialize it.
7242              
7243 633 100       1326 if ( not( defined( $global_true_or_false_ignore_case[ $global_case_number ] ) ) )
7244             {
7245 15         24 $global_true_or_false_ignore_case[ $global_case_number ] = $global_false ;
7246             }
7247              
7248              
7249             #-----------------------------------------------
7250             # Handle the code for a question number.
7251              
7252 633 100       2331 if ( $current_vote_info_number == $global_voteinfo_code_for_question_number )
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
    100          
    100          
    100          
    100          
    100          
7253             {
7254 98         116 $status_pair_just_handled = $global_true ;
7255 98 50       201 if ( $global_true_or_false_ignore_case[ $global_case_number ] == $global_true )
7256             {
7257 0         0 next ;
7258             }
7259 98         108 $global_question_number = $next_vote_info_number ;
7260 98 50       249 if ( $global_question_number < 0 )
    50          
7261             {
7262 0         0 $global_true_or_false_ignore_case[ $global_case_number ] = $global_true ;
7263 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[question-number-less-than-one (at list position " . $pointer_to_vote_info . ")]" } ;
  0         0  
7264 0         0 $global_output_warning_messages_case_or_question_specific .= $global_case_specific_warning_begin . " contains-question-number-less-than-one" . $global_warning_end ;
7265 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[ignoring case " . $global_case_number . "]" } ;
  0         0  
7266             } elsif ( $global_question_number > $global_maximum_question_number )
7267             {
7268 0         0 $global_true_or_false_ignore_case[ $global_case_number ] = $global_true ;
7269 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[too_many-questions-in-case (limit is " . $global_maximum_question_number . ", case is " . $global_case_number . ")]" } ;
  0         0  
7270 0         0 $global_output_warning_messages_case_or_question_specific .= $global_case_specific_warning_begin . " has-too-many-questions-limit-is " . $global_maximum_question_number . ")" . $global_warning_end ;
7271 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[ignoring case " . $global_case_number . "]" } ;
  0         0  
7272             } else
7273             {
7274 98         137 $global_question_count_for_case[ $global_case_number ] = $global_question_number ;
7275 98         103 $global_number_of_questions_in_current_case = $global_question_number ;
7276 98 50       227 if ( $global_logging_info == $global_true ) { print LOGOUT "[question " . $global_question_number . "]" } ;
  98         212  
7277 98         124 $tally_uses_of_question_number[ $global_question_number ] ++ ;
7278 98         114 $count_of_choices_marked_for_current_question = 0 ;
7279 98         406 $global_question_specific_warning_begin = "case-" . $global_case_number . "-question-" . $global_question_number . "-warning-message:\n" . "word-case-capitalized " . $global_case_number . " word-question " . $global_question_number ;
7280             }
7281              
7282              
7283             #-----------------------------------------------
7284             # Handle the code for a choice count.
7285              
7286             } elsif ( $current_vote_info_number == $global_voteinfo_code_for_number_of_choices )
7287             {
7288 22         30 $status_pair_just_handled = $global_true ;
7289 22 50       55 if ( $global_true_or_false_ignore_case[ $global_case_number ] == $global_true )
7290             {
7291 0         0 next ;
7292             }
7293 22         53 $global_choice_count_for_case_and_question[ $global_case_number ][ $global_question_number ] = $next_vote_info_number ;
7294 22         23 $choice_count_for_current_question = $next_vote_info_number ;
7295 22 50       58 if ( $global_logging_info == $global_true ) { print LOGOUT "[choice count " . $choice_count_for_current_question . "]" } ;
  22         52  
7296 22 50       57 if ( $global_question_number == 0 )
7297             {
7298 0         0 $global_true_or_false_ignore_case[ $global_case_number ] = $global_true ;
7299 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[encountered-choice-count-without-question-number (case " . $global_case_number . ", question " . $global_question_number . ", at list position " . $pointer_to_vote_info . ")]" } ;
  0         0  
7300 0         0 $global_output_warning_messages_case_or_question_specific .= $global_case_specific_warning_begin . " contains-choice-count-without-question-number" . $global_warning_end ;
7301 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[ignoring case " . $global_case_number . "]" } ;
  0         0  
7302             }
7303 22 50 33     154 if ( ( $choice_count_for_current_question < 1 ) || ( $choice_count_for_current_question > $global_maximum_choice_number ) )
7304             {
7305 0         0 $global_true_or_false_ignore_case[ $global_case_number ] = $global_true ;
7306 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[invalid-choice-count (case " . $global_case_number . ", choice count " . $choice_count_for_current_question . ", list position " . $pointer_to_vote_info . ")]" } ;
  0         0  
7307 0         0 $global_output_warning_messages_case_or_question_specific .= $global_case_specific_warning_begin . " contains-invalid-choice-count (" . $choice_count_for_current_question . ")" . $global_warning_end ;
7308 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[ignoring case " . $global_case_number . "]" } ;
  0         0  
7309             }
7310              
7311              
7312             #-----------------------------------------------
7313             # Handle the code for a ballot count.
7314              
7315             } elsif ( $current_vote_info_number == $global_voteinfo_code_for_ballot_count )
7316             {
7317 73         78 $status_pair_just_handled = $global_true ;
7318 73 50       147 if ( $global_true_or_false_ignore_case[ $global_case_number ] == $global_true )
7319             {
7320 0         0 next ;
7321             }
7322 73         78 $global_ballot_info_repeat_count = $next_vote_info_number ;
7323 73 50       156 if ( $global_ballot_info_repeat_count < 1 )
7324             {
7325 0         0 $global_true_or_false_ignore_case[ $global_case_number ] = $global_true ;
7326 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[ballot-count-number-less-than-one (at list position " . $pointer_to_vote_info . ")]" } ;
  0         0  
7327 0         0 $global_output_warning_messages_case_or_question_specific .= $global_case_specific_warning_begin . " has-ballot-count-number-less-than-one" . $global_warning_end ;
7328 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[ignoring case " . $global_case_number . "]" } ;
  0         0  
7329             }
7330 73 50       132 if ( $global_logging_info == $global_true ) { print LOGOUT "[bc " . $global_ballot_info_repeat_count . "]" } ;
  73         265  
7331              
7332              
7333             #-----------------------------------------------
7334             # Handle the code for a choice number.
7335              
7336             } elsif ( $current_vote_info_number > 0 )
7337             {
7338 344         355 $global_choice_number = $current_vote_info_number ;
7339 344 50       656 if ( $global_true_or_false_ignore_case[ $global_case_number ] == $global_true )
7340             {
7341 0         0 next ;
7342             }
7343 344 50       779 if ( $global_case_number < 1 )
7344             {
7345 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[positive-number-encountered-before-first-case-number]" } ;
  0         0  
7346 0         0 return "Error: Positive number encountered before first case number" ;
7347             }
7348 344 50       1422 if ( $global_question_number < 1 )
    50          
    50          
    100          
7349             {
7350 0         0 $global_true_or_false_ignore_case[ $global_case_number ] = $global_true ;
7351 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[choice-number-not-preceded-by-question-number (at list position " . $pointer_to_vote_info . ")]" } ;
  0         0  
7352 0         0 $global_output_warning_messages_case_or_question_specific .= $global_case_specific_warning_begin . " contains-choice-number-without-question-number" . $global_warning_end ;
7353 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[ignoring case " . $global_case_number . "]" } ;
  0         0  
7354             } elsif ( not( defined( $global_choice_count_for_case_and_question[ $global_case_number ][ $global_question_number ] ) ) )
7355             {
7356 0         0 $global_true_or_false_ignore_case[ $global_case_number ] = $global_true ;
7357 0         0 $global_output_warning_messages_case_or_question_specific .= $global_case_specific_warning_begin . " contains-choice-number-that-appears-before-number-of-choices-specified " . $global_warning_end ;
7358 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[choice-number-appears-before-number-of-choices-specified (case " . $global_case_number . ", question " . $global_question_number . ", ballot vote count " . $global_ballot_info_repeat_count . ", choice " . $global_choice_number . ", at list position " . $pointer_to_vote_info . ")]" } ;
  0         0  
7359 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[ignoring case " . $global_case_number . "]" } ;
  0         0  
7360             } elsif ( $global_choice_number > $global_choice_count_for_case_and_question[ $global_case_number ][ $global_question_number ] )
7361             {
7362 0         0 $global_true_or_false_ignore_case[ $global_case_number ] = $global_true ;
7363 0         0 $global_output_warning_messages_case_or_question_specific .= $global_case_specific_warning_begin . " contains-choice-number (" . $global_choice_number . ") that-exceeds-number-of-choices (" . $global_choice_count_for_case_and_question[ $global_case_number ][ $global_question_number ] . ")" . $global_warning_end ;
7364 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[choice-number-exceeds-indicated-number-of-choices (case " . $global_case_number . ", question " . $global_question_number . ", ballot vote count " . $global_ballot_info_repeat_count . ", choice " . $global_choice_number . ", specified number " . $global_choice_count_for_case_and_question[ $global_case_number ][ $global_question_number ] . ", at list position " . $pointer_to_vote_info . ")]" } ;
  0         0  
7365 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[ignoring case " . $global_case_number . "]" } ;
  0         0  
7366             } elsif ( defined( $tally_uses_of_choice_number[ $global_choice_number ] ) )
7367             {
7368 240 50       559 if ( $tally_uses_of_choice_number[ $global_choice_number ] > 1 )
7369             {
7370 0         0 $global_true_or_false_ignore_case[ $global_case_number ] = $global_true ;
7371 0         0 $global_output_warning_messages_case_or_question_specific .= $global_case_specific_warning_begin . " contains-choice-number (" . $global_choice_number . ") that-is-used-more-than-once-in-same-ballot" . $global_warning_end ;
7372 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[choice-number-previously-used-in-this-ballot (case " . $global_case_number . ", question " . $global_question_number . ", ballot vote count " . $global_ballot_info_repeat_count . ", choice " . $global_choice_number . ", at list position " . $pointer_to_vote_info . ")]" } ;
  0         0  
7373 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[ignoring case " . $global_case_number . "]" } ;
  0         0  
7374             }
7375             }
7376 344 50       1106 if ( $global_true_or_false_ignore_case[ $global_case_number ] == $global_false )
7377             {
7378 344         466 $tally_uses_of_choice_number[ $global_choice_number ] = 1 ;
7379 344         332 $count_of_choices_marked_for_current_question ++ ;
7380 344 50       701 if ( $global_choice_number > $global_choice_count_for_case_and_question[ $global_case_number ][ $global_question_number ] )
7381             {
7382 0         0 $global_choice_count_for_case_and_question[ $global_case_number ][ $global_question_number ] = $global_choice_number ;
7383             }
7384 344         375 $global_current_total_vote_count += $global_ballot_info_repeat_count ;
7385 344         330 $global_ballot_info_repeat_count = 0 ;
7386 344 50       597 if ( $global_logging_info == $global_true ) { print LOGOUT "[" . $global_choice_number . "]" } ;
  344         1234  
7387             }
7388              
7389              
7390             #-----------------------------------------------
7391             # Handle the code for a tie.
7392              
7393             } elsif ( $current_vote_info_number == $global_voteinfo_code_for_tie )
7394             {
7395 10 50       21 if ( $global_true_or_false_ignore_case[ $global_case_number ] == $global_true )
7396             {
7397 0         0 next ;
7398             }
7399 10 50 33     39 if ( ( $count_of_choices_marked_for_current_question < 1 ) || ( $global_question_number < 1 ) )
7400             {
7401 0         0 $global_true_or_false_ignore_case[ $global_case_number ] = $global_true ;
7402 0         0 $global_output_warning_messages_case_or_question_specific .= $global_case_specific_warning_begin . " contains-invalid-nesting-of-tie-indicator" . $global_warning_end ;
7403 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[invalid-nesting-of-tied-preference-vote-info-number (case " . $global_case_number . ", question " . $global_question_number . ", ballot vote count " . $global_current_total_vote_count . ", at list position " . $pointer_to_vote_info . ")]" } ;
  0         0  
7404 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[ignoring case " . $global_case_number . "]" } ;
  0         0  
7405             }
7406 10 50       26 if ( $global_true_or_false_ignore_case[ $global_case_number ] == $global_false )
7407             {
7408 10 50       16 if ( $global_logging_info == $global_true ) { print LOGOUT "[+]" } ;
  10         30  
7409             }
7410              
7411              
7412             #-----------------------------------------------
7413             # Handle the code for the beginning of all the
7414             # ballots (for this case).
7415              
7416             } elsif ( $current_vote_info_number == $global_voteinfo_code_for_start_of_all_vote_info )
7417             {
7418 2 50       9 if ( $global_true_or_false_ignore_case[ $global_case_number ] == $global_true )
7419             {
7420 0         0 next ;
7421             }
7422 2         6 $global_question_number = 0 ;
7423 2 50       7 if ( $global_logging_info == $global_true ) { print LOGOUT "[begin ballots]" } ;
  2         9  
7424              
7425              
7426             #-----------------------------------------------
7427             # Handle the code for the end of a ballot.
7428              
7429             } elsif ( $current_vote_info_number == $global_voteinfo_code_for_end_of_ballot )
7430             {
7431 4 50       12 if ( $global_true_or_false_ignore_case[ $global_case_number ] == $global_true )
7432             {
7433 0         0 next ;
7434             }
7435 4         9 @tally_uses_of_choice_number = ( ) ;
7436 4         14 $global_question_number = 0 ;
7437             # if ( $global_logging_info == $global_true ) { print LOGOUT "[end ballot]" } ;
7438              
7439              
7440             #-----------------------------------------------
7441             # Handle the code for the end of all vote info
7442             # (for the current case).
7443              
7444             } elsif ( $current_vote_info_number == $global_voteinfo_code_for_end_of_all_vote_info )
7445             {
7446 3 50       11 if ( $global_logging_info == $global_true ) { print LOGOUT "[end ballots for case " . $global_case_number . "]" } ;
  3         14  
7447              
7448              
7449             #-----------------------------------------------
7450             # Handle the code for the end of all cases.
7451              
7452             } elsif ( $current_vote_info_number == $global_voteinfo_code_for_end_of_all_cases )
7453             {
7454 17 50       51 if ( $global_case_number < 1 )
7455             {
7456 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[reached end of all cases, but no case has been started]" } ;
  0         0  
7457 0         0 return "Error: Reached end of all cases before first case started (list position " . $pointer_to_vote_info . ")" ;
7458             }
7459 17 50       36 if ( $global_logging_info == $global_true ) { print LOGOUT "[end of all cases]" } ;
  17         62  
7460              
7461              
7462             #-----------------------------------------------
7463             # Handle the code for a request to calculate
7464             # VoteFair representation ranking results,
7465             # VoteFair party ranking results, or only do
7466             # plurality counting. If this request occurs
7467             # before the first case number, apply this
7468             # request to all cases and all questions,
7469             # although a different request can be specified
7470             # (later) for a specific question. If the
7471             # request does not appear before the first
7472             # ballot (in the case), indicate (in the log
7473             # file) an error, but allow this minor error.
7474              
7475             } elsif ( $current_vote_info_number == $global_voteinfo_code_for_request_only_plurality_results )
7476             {
7477 1 50       4 if ( $global_case_number < 1 )
    0          
7478             {
7479 1         2 $global_true_or_false_always_request_only_plurality_results = $global_true ;
7480 1 50       3 if ( $global_logging_info == $global_true ) { print LOGOUT "\n[found all-cases request for only plurality counts]\n" } ;
  1         3  
7481             } elsif ( $global_current_total_vote_count > 0 )
7482             {
7483 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "\n[found special request after first ballot started, this request will be ignored]\n" } ;
  0         0  
7484             }
7485             } elsif ( $current_vote_info_number == $global_voteinfo_code_for_request_pairwise_counts )
7486             {
7487 0 0       0 if ( $global_case_number < 1 )
    0          
7488             {
7489 0         0 $global_true_or_false_always_request_no_pairwise_counts = $global_false ;
7490 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "\n[found all-cases request for pairwise counts]\n" } ;
  0         0  
7491             } elsif ( $global_current_total_vote_count > 0 )
7492             {
7493 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "\n[found special request after first ballot started, this request will be ignored]\n" } ;
  0         0  
7494             }
7495             } elsif ( $current_vote_info_number == $global_voteinfo_code_for_request_no_pairwise_counts )
7496             {
7497 9 50       21 if ( $global_case_number < 1 )
    0          
7498             {
7499 9         13 $global_true_or_false_always_request_no_pairwise_counts = $global_true ;
7500 9 50       26 if ( $global_logging_info == $global_true ) { print LOGOUT "\n[found all-cases request for no pairwise counts]\n" } ;
  9         39  
7501             } elsif ( $global_current_total_vote_count > 0 )
7502             {
7503 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "\n[found special request after first ballot started, this request will be ignored]\n" } ;
  0         0  
7504             }
7505             } elsif ( $current_vote_info_number == $global_voteinfo_code_for_request_votefair_representation_rank )
7506             {
7507 10 50       34 if ( $global_case_number < 1 )
    0          
7508             {
7509 10         14 $global_true_or_false_always_request_votefair_representation_rank = $global_true ;
7510 10 50       31 if ( $global_logging_info == $global_true ) { print LOGOUT "\n[found all-cases request for VoteFair representation ranking results]\n" } ;
  10         41  
7511             } elsif ( $global_current_total_vote_count > 0 )
7512             {
7513 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "\n[found special request after first ballot started, this request will be ignored]\n" } ;
  0         0  
7514             }
7515             } elsif ( $current_vote_info_number == $global_voteinfo_code_for_request_no_votefair_representation_rank )
7516             {
7517 4 50       43 if ( $global_case_number < 1 )
    0          
7518             {
7519 4         6 $global_true_or_false_always_request_votefair_representation_rank = $global_false ;
7520 4 50       22 if ( $global_logging_info == $global_true ) { print LOGOUT "\n[found all-cases request for no VoteFair representation ranking results]\n" } ;
  4         18  
7521             } elsif ( $global_current_total_vote_count > 0 )
7522             {
7523 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "\n[found special request after first ballot started, this request will be ignored]\n" } ;
  0         0  
7524             }
7525             } elsif ( $current_vote_info_number == $global_voteinfo_code_for_request_votefair_party_rank )
7526             {
7527 10 50       22 if ( $global_case_number < 1 )
    0          
7528             {
7529 10         19 $global_true_or_false_always_request_votefair_party_rank = $global_true ;
7530 10 50       33 if ( $global_logging_info == $global_true ) { print LOGOUT "\n[found all-cases request for VoteFair party ranking results]\n" } ;
  10         37  
7531             } elsif ( $global_current_total_vote_count > 0 )
7532             {
7533 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "\n[found special request after first ballot started, this request will be ignored]\n" } ;
  0         0  
7534             }
7535             } elsif ( $current_vote_info_number == $global_voteinfo_code_for_request_no_votefair_party_rank )
7536             {
7537 4 50       10 if ( $global_case_number < 1 )
    0          
7538             {
7539 4         8 $global_true_or_false_always_request_votefair_party_rank = $global_false ;
7540 4 50       22 if ( $global_logging_info == $global_true ) { print LOGOUT "\n[found all-cases request for no VoteFair party ranking results]\n" } ;
  4         15  
7541             } elsif ( $global_current_total_vote_count > 0 )
7542             {
7543 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "\n[found special request after first ballot started, this request will be ignored]\n" } ;
  0         0  
7544             }
7545              
7546              
7547             #-----------------------------------------------
7548             # If the code was not recognized, indicate this
7549             # situation in the log file, but do not indicate
7550             # an error (because it will be ignored).
7551              
7552             } else
7553             {
7554 22 50       47 if ( $global_logging_info == $global_true ) { print LOGOUT "[unrecognized code: " . $current_vote_info_number . "]" } ;
  22         87  
7555             }
7556              
7557              
7558             #-----------------------------------------------
7559             # Repeat the loop that gets the next vote-info
7560             # number in the list.
7561              
7562             }
7563              
7564              
7565             #-----------------------------------------------
7566             # If the code for the end of all cases was not
7567             # the last code encountered, extend the list by
7568             # one more number, and insert the
7569             # end-of-all-cases code.
7570              
7571 17 50       49 if ( $current_vote_info_number != $global_voteinfo_code_for_end_of_all_cases )
7572             {
7573 0         0 $global_length_of_vote_info_list ++ ;
7574 0         0 $global_vote_info_list[ $global_length_of_vote_info_list ] = $global_voteinfo_code_for_end_of_all_cases ;
7575             }
7576              
7577              
7578             #-----------------------------------------------
7579             # End of subroutine.
7580              
7581 17 50       41 if ( $global_logging_info == $global_true ) { print LOGOUT "\n\n[done checking vote info numbers]\n\n" } ;
  17         26  
7582 17         66 return "" ;
7583              
7584             }
7585              
7586              
7587              
7588              
7589             =head2 calculate_results_for_one_question
7590              
7591             (Not exported, for internal use only.)
7592              
7593             Calculates voting results for one question
7594             (contest) in an election/poll/survey.
7595              
7596             =cut
7597              
7598             #-----------------------------------------------
7599             #-----------------------------------------------
7600             # calculate_results_for_one_question
7601             #-----------------------------------------------
7602             #-----------------------------------------------
7603              
7604             sub calculate_results_for_one_question
7605             {
7606              
7607 19     19 1 30 my $actual_choice ;
7608             my $adjusted_choice ;
7609 0         0 my $ranking_level ;
7610 0         0 my $popularity_level ;
7611 0         0 my $representation_level ;
7612 0         0 my $party_level ;
7613 0         0 my $current_vote_info_number ;
7614 0         0 my $sequence_position ;
7615 0         0 my $context_question_number ;
7616 0         0 my $possible_text_rep_not_the_same ;
7617 0         0 my $possible_text_party_not_the_same ;
7618 0         0 my $comparison_of_methods_table ;
7619 0         0 my $total_vote_count_for_current_question ;
7620              
7621              
7622             #-----------------------------------------------
7623             # These values must already be set:
7624             # (They are not checked for validity because
7625             # that is done before getting here.)
7626             # $global_input_pointer_start_next_case
7627             # $global_case_number
7628             # $global_question_number
7629             # $global_full_choice_count
7630              
7631              
7632             #-----------------------------------------------
7633             # In case it is needed, initialize a prefix for
7634             # any warning message that refers to this
7635             # question.
7636              
7637 19 50       50 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, beginning to do calculations for question " . $global_question_number . "]\n" } ;
  19         50  
7638 19         75 $global_question_specific_warning_begin = "case-" . $global_case_number . "-question-" . $global_question_number . "-warning-message:\n" . "word-case-capitalized " . $global_case_number . " word-question " . $global_question_number ;
7639              
7640              
7641             #-----------------------------------------------
7642             # Initialize the flags that determine whether
7643             # or not to do VoteFair representation ranking
7644             # and VoteFair party ranking. These flags
7645             # can change (below) if requested for this case.
7646              
7647 19         28 $global_true_or_false_request_votefair_popularity_rank = $global_true ;
7648 19         27 $global_true_or_false_request_only_plurality_results = $global_true_or_false_always_request_only_plurality_results ;
7649 19         26 $global_true_or_false_request_no_pairwise_counts = $global_true_or_false_always_request_no_pairwise_counts ;
7650 19         57 $global_true_or_false_request_votefair_representation_rank = $global_true_or_false_always_request_votefair_representation_rank ;
7651 19         27 $global_true_or_false_request_votefair_party_rank = $global_true_or_false_always_request_votefair_party_rank ;
7652              
7653              
7654             #-----------------------------------------------
7655             # Clear the result lists in case some
7656             # calculations are not done.
7657              
7658 19         58 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
7659             {
7660 105         134 $global_plurality_count_for_actual_choice[ $actual_choice ] = 0 ;
7661 105         118 $global_popularity_ranking_for_actual_choice[ $actual_choice ] = 0 ;
7662 105         119 $global_full_popularity_ranking_for_actual_choice[ $actual_choice ] = 0 ;
7663 105         118 $global_representation_ranking_for_actual_choice[ $actual_choice ] = 0 ;
7664 105         123 $global_full_representation_ranking_for_actual_choice[ $actual_choice ] = 0 ;
7665 105         239 $global_party_ranking_for_actual_choice[ $actual_choice ] = 0 ;
7666             }
7667              
7668              
7669             #-----------------------------------------------
7670             # Set up pointers and lists and values that
7671             # will be used for this question.
7672              
7673 19 50       44 if ( $global_logging_info == $global_true ) { print LOGOUT "\n" } ;
  19         37  
7674 19         59 &set_all_choices_as_used( ) ;
7675 19         61 &reset_ballot_info_and_tally_table( ) ;
7676 19         31 $global_ballot_influence_amount = 1.0 ;
7677 19         36 $global_ballot_info_repeat_count = 0 ;
7678 19         26 $global_current_total_vote_count = 0 ;
7679 19 50       43 if ( $global_logging_info == $global_true ) { print LOGOUT "\n" } ;
  19         39  
7680              
7681              
7682             #-----------------------------------------------
7683             # At the beginning of the vote info, look for
7684             # any requests regarding which calculations
7685             # should, or should not, be done. Only check
7686             # as far as the end of the first ballot.
7687             # Also update the
7688             # "global_input_pointer_start_next_case"
7689             # pointer to skip over the code that indicates
7690             # how many choices are in each question.
7691              
7692 19         21 $context_question_number = 0 ;
7693 19         25 $global_pointer_to_current_ballot = $global_input_pointer_start_next_case ;
7694 19         73 while ( $global_pointer_to_current_ballot < $global_max_array_length )
7695             {
7696 612         710 $current_vote_info_number = $global_vote_info_list[ $global_pointer_to_current_ballot ] ;
7697 612 100 100     5205 if ( ( $current_vote_info_number == $global_voteinfo_code_for_end_of_ballot ) || ( $current_vote_info_number == $global_voteinfo_code_for_end_of_all_vote_info ) || ( $current_vote_info_number == $global_voteinfo_code_for_case_number ) || ( $current_vote_info_number == $global_voteinfo_code_for_end_of_all_cases ) )
    100 100        
    100 100        
    100          
7698             {
7699 19         38 last ;
7700             } elsif ( $current_vote_info_number == $global_voteinfo_code_for_question_number )
7701             {
7702 92         96 $global_pointer_to_current_ballot ++ ;
7703 92         131 $context_question_number = $global_vote_info_list[ $global_pointer_to_current_ballot ] ;
7704             } elsif ( $current_vote_info_number == $global_voteinfo_code_for_number_of_choices )
7705             {
7706 20         24 $global_pointer_to_current_ballot ++ ;
7707 20         25 $global_input_pointer_start_next_case = $global_pointer_to_current_ballot + 1 ;
7708             } elsif ( $context_question_number == $global_question_number )
7709             {
7710 464 50       1755 if ( $current_vote_info_number == $global_voteinfo_code_for_request_only_plurality_results )
    50          
    50          
    50          
7711             {
7712 0         0 $global_true_or_false_request_only_plurality_results = $global_true ;
7713 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, request for only plurality results]" } ;
  0         0  
7714             } elsif ( $current_vote_info_number == $global_voteinfo_code_for_request_no_pairwise_counts )
7715             {
7716 0         0 $global_true_or_false_request_no_pairwise_counts = $global_true ;
7717 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, request for no pairwise counts]" } ;
  0         0  
7718             } elsif ( $current_vote_info_number == $global_voteinfo_code_for_request_votefair_representation_rank )
7719             {
7720 0         0 $global_true_or_false_request_votefair_representation_rank = $global_true ;
7721 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, request for representation ranking results]" } ;
  0         0  
7722             } elsif ( $current_vote_info_number == $global_voteinfo_code_for_request_votefair_party_rank )
7723             {
7724 0         0 $global_true_or_false_request_votefair_party_rank = $global_true ;
7725 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, request for party ranking results]" } ;
  0         0  
7726             }
7727             }
7728 593         1140 $global_pointer_to_current_ballot ++ ;
7729             }
7730              
7731              
7732             #-----------------------------------------------
7733             # Log the status for what is being requested,
7734             # for this question and for all questions.
7735              
7736 19 50       48 if ( $global_logging_info == $global_true )
7737             {
7738 19         35 print LOGOUT "[one question, requests: " ;
7739 19 100       49 if ( $global_true_or_false_request_only_plurality_results == $global_true )
7740             {
7741 1         2 print LOGOUT "request for only plurality results" ;
7742             } else
7743             {
7744 18         51 print LOGOUT "no special request for only plurality results" ;
7745             }
7746 19 100       47 if ( $global_true_or_false_request_no_pairwise_counts == $global_true )
7747             {
7748 13         27 print LOGOUT " ; request for no pairwise counts" ;
7749             } else
7750             {
7751 6         24 print LOGOUT " ; pairwise counts will be included" ;
7752             }
7753 19 100       39 if ( $global_true_or_false_request_votefair_representation_rank == $global_true )
7754             {
7755 14         29 print LOGOUT " ; request for VoteFair representation ranking results" ;
7756             } else
7757             {
7758 5         10 print LOGOUT " ; request for no VoteFair representation ranking results" ;
7759             }
7760 19 100       45 if ( $global_true_or_false_request_votefair_party_rank == $global_true )
7761             {
7762 14         23 print LOGOUT " ; request for VoteFair party ranking results" ;
7763             } else
7764             {
7765 5         7 print LOGOUT " ; request for no VoteFair party ranking results" ;
7766             }
7767 19         33 print LOGOUT "]\n" ;
7768             }
7769              
7770              
7771             #-----------------------------------------------
7772             # If there are not at least two choices,
7773             # indicate an error.
7774              
7775 19 50       60 if ( $global_adjusted_choice_count < 2 )
7776             {
7777 0         0 $global_output_warning_messages_case_or_question_specific .= $global_question_specific_warning_begin . " does-not-have-at-least-two-choices" . "\n-----\n\n" ;
7778 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, ERROR: number of (adjusted) choices is less than two]\n" } ;
  0         0  
7779 0         0 return ;
7780             }
7781              
7782              
7783             #-----------------------------------------------
7784             # Do the pairwise counting -- for all the
7785             # ballots and all the choices, with no special
7786             # weighting.
7787             # As part of getting the ballot information,
7788             # count the plurality results.
7789             # Also, if any requests for specific results
7790             # -- such as plurality counts only -- are
7791             # encountered, set the appropriate flag.
7792              
7793 19         30 $global_pointer_to_current_ballot = $global_input_pointer_start_next_case ;
7794 19         57 $global_ballot_info_repeat_count = &get_numbers_based_on_one_ballot( ) ;
7795 19         51 while ( $global_ballot_info_repeat_count > 0 )
7796             {
7797 72         134 &add_preferences_to_tally_table( ) ;
7798 72         123 $global_ballot_info_repeat_count = &get_numbers_based_on_one_ballot( ) ;
7799             }
7800 19         26 $total_vote_count_for_current_question = $global_current_total_vote_count ;
7801 19 50       40 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, total vote count is " . $total_vote_count_for_current_question . "]\n" } ;
  19         118  
7802              
7803              
7804             #-----------------------------------------------
7805             # If there were no ballots, indicate this in
7806             # the results, and exit this subroutine.
7807              
7808 19 50       56 if ( $total_vote_count_for_current_question == 0 )
7809             {
7810 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, no ballots for this question, so no calculations done]\n" } ;
  0         0  
7811 0         0 $global_output_warning_messages_case_or_question_specific .= $global_question_specific_warning_begin . " words-contains-no-ballots" . "\n-----\n\n" ;
7812 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, this question has no ballots]\n" } ;
  0         0  
7813 0         0 &put_next_result_info_number( $global_voteinfo_code_for_skip_question ) ;
7814 0         0 return ;
7815             }
7816              
7817              
7818             #-----------------------------------------------
7819             # Output the plurality results.
7820              
7821 19         55 &output_plurality_counts( ) ;
7822              
7823              
7824             #-----------------------------------------------
7825             # If only plurality results are requested,
7826             # exit this subroutine.
7827              
7828 19 100       51 if ( $global_true_or_false_request_only_plurality_results == $global_true )
7829             {
7830 1 50       4 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, only plurality results requested, so further calculations not done]\n" } ;
  1         2  
7831 1         3 $global_output_warning_messages_case_or_question_specific .= $global_question_specific_warning_begin . " does-not-request-VoteFair-calculations-only-plurality-counts" . "\n-----\n\n" ;
7832 1 50       3 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, all done for question " . $global_question_number . " in case " . $global_case_number . "]\n" } ;
  1         3  
7833 1         2 return ;
7834             }
7835              
7836              
7837             #-----------------------------------------------
7838             # Log a display of the tally numbers in
7839             # an array version.
7840              
7841 18 50       43 if ( $global_logging_info == $global_true )
7842             {
7843 18         50 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
7844             {
7845 102         236 $global_log_info_choice_at_position[ $actual_choice ] = $actual_choice ;
7846             }
7847 18         32 print LOGOUT "[one question, full pairwise counts ranking:]\n" ;
7848 18         38 &internal_view_matrix( ) ;
7849             }
7850              
7851              
7852             #-----------------------------------------------
7853             # Unless suppressed, output the pairwise counts
7854             # -- while the pairwise counts for all the
7855             # choices are still in the tally table.
7856              
7857 18 100       57 if ( $global_true_or_false_request_no_pairwise_counts == $global_false )
7858             {
7859 5         17 &output_tally_table_numbers( ) ;
7860 5 50       15 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, pairwise counts put into output list]\n" } ;
  5         15  
7861             }
7862              
7863              
7864             #-----------------------------------------------
7865             # Do the VoteFair popularity ranking
7866             # calculations.
7867              
7868 18         46 $global_ranking_type_being_calculated = "popularity" ;
7869 18 50       54 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, VoteFair popularity ranking calculations beginning]\n" } ;
  18         30  
7870 18         23 $global_pointer_to_current_ballot = $global_input_pointer_start_next_case ;
7871 18         54 &calc_votefair_popularity_rank( ) ;
7872 18 50       50 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, VoteFair popularity ranking calculations done]\n" } ;
  18         45  
7873 18 50       58 if ( $global_possible_error_message ne "" )
7874             {
7875 0         0 return ;
7876             }
7877              
7878              
7879             #-----------------------------------------------
7880             # If the popularity results were not calculated,
7881             # the error message has already been written,
7882             # so just return.
7883              
7884 18         25 $adjusted_choice = 1 ;
7885 18         32 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
7886 18 50       583 if ( $global_popularity_ranking_for_actual_choice[ $actual_choice ] == 0 )
7887             {
7888 0         0 return ;
7889             }
7890              
7891              
7892             #-----------------------------------------------
7893             # Save the VoteFair popularity ranking results
7894             # that apply to all the choices (because the
7895             # rankings will be overwritten if VoteFair
7896             # representation ranking or VoteFair party
7897             # ranking calculations are done).
7898             # Also save the top-ranked choice -- if it is
7899             # a single winning choice -- for use by
7900             # the representation and party ranking
7901             # calculations.
7902              
7903 18         28 $global_choice_count_at_full_top_popularity_ranking_level = 0 ;
7904 18         31 $global_actual_choice_at_top_of_full_popularity_ranking = 0 ;
7905 18         59 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
7906             {
7907 102         219 $global_full_popularity_ranking_for_actual_choice[ $actual_choice ] = $global_popularity_ranking_for_actual_choice[ $actual_choice ] ;
7908 102 100       277 if ( $global_full_popularity_ranking_for_actual_choice[ $actual_choice ] == 1 )
7909             {
7910 27         34 $global_actual_choice_at_top_of_full_popularity_ranking = $actual_choice ;
7911 27         66 $global_choice_count_at_full_top_popularity_ranking_level ++ ;
7912             }
7913             }
7914 18 100       54 if ( $global_choice_count_at_full_top_popularity_ranking_level != 1 )
7915             {
7916 8         10 $global_actual_choice_at_top_of_full_popularity_ranking = 0 ;
7917             }
7918 18 50       52 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, number of most-popular choices is " . $global_choice_count_at_full_top_popularity_ranking_level . "]\n" } ;
  18         58  
7919 18 50       56 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, if only one top choice, choice number is " . $global_actual_choice_at_top_of_full_popularity_ranking . "]\n" } ;
  18         51  
7920              
7921              
7922             #-----------------------------------------------
7923             # Log a display of the tally numbers with the
7924             # choices in popularity ranking sequence.
7925              
7926 18 50       46 if ( $global_logging_info == $global_true )
7927             {
7928 18         32 $sequence_position = 1 ;
7929 18         68 for ( $ranking_level = 1 ; $ranking_level <= $global_full_choice_count ; $ranking_level ++ )
7930             {
7931 102         213 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
7932             {
7933 742 100       2028 if ( $global_full_popularity_ranking_for_actual_choice[ $actual_choice ] == $ranking_level )
7934             {
7935 102         128 $global_log_info_choice_at_position[ $sequence_position ] = $actual_choice ;
7936 102         219 $sequence_position ++ ;
7937             }
7938             }
7939             }
7940 18         37 print LOGOUT "[one question, pairwise counts in VoteFair popularity ranking sequence:]\n" ;
7941 18         40 &internal_view_matrix( ) ;
7942             }
7943              
7944              
7945             #-----------------------------------------------
7946             # Determine how many levels of representation
7947             # ranking should be done.
7948             #
7949             # If VoteFair party ranking results are
7950             # requested, request at least two levels of
7951             # VoteFair representation ranking results.
7952              
7953 18         30 $global_representation_levels_requested = $global_default_representation_levels_requested ;
7954 18 100       46 if ( $global_true_or_false_request_votefair_representation_rank == $global_true )
7955             {
7956 14         30 $global_representation_levels_requested = $global_limit_on_representation_rank_levels ;
7957 14 50       35 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, for representation ranking, calculation limit used]\n" } ;
  14         262  
7958             } else
7959             {
7960 4         7 $global_representation_levels_requested = 0 ;
7961 4 50       13 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, no representation ranking requested]\n" } ;
  4         12  
7962             }
7963 18 100       47 if ( $global_true_or_false_request_votefair_party_rank == $global_true )
7964             {
7965 14 50       46 if ( $global_representation_levels_requested < 2 )
7966             {
7967 0         0 $global_representation_levels_requested = 2 ;
7968 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, for party ranking, minimum of two representation levels requested]\n" } ;
  0         0  
7969             }
7970             }
7971 18 100       60 if ( $total_vote_count_for_current_question < 2 )
7972             {
7973 2         3 $global_representation_levels_requested = 0 ;
7974 2         10 $global_output_warning_messages_case_or_question_specific .= "case-" . $global_case_number . "-question-" . $global_question_number . "-results-type-representation-warning-message:\n" . "not-at-least-two-ballots-so-no-representation-calculations-done" . $global_warning_end ;
7975 2 50       6 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, not at least two ballots, so no representation levels calculated]\n" } ;
  2         7  
7976             }
7977              
7978              
7979             #-----------------------------------------------
7980             # If requested, do VoteFair representation
7981             # ranking -- using all the choices.
7982              
7983 18 100       47 if ( $global_representation_levels_requested > 1 )
7984             {
7985 12         28 $global_ranking_type_being_calculated = "representation" ;
7986 12 50       34 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, VoteFair representation ranking calculations beginning]\n" } ;
  12         15  
7987 12         28 $global_pointer_to_current_ballot = $global_input_pointer_start_next_case ;
7988 12         41 &set_all_choices_as_used( ) ;
7989 12         37 &calc_votefair_representation_rank( ) ;
7990 12 50       51 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, VoteFair representation ranking calculations end]\n" } ;
  12         31  
7991              
7992              
7993             #-----------------------------------------------
7994             # If they were calculated, save the VoteFair
7995             # representation ranking results that apply
7996             # to all the choices (because these rankings
7997             # will be overwritten if VoteFair party
7998             # ranking calculations are done).
7999             # Also save the second-ranked representation
8000             # choice -- if it does not involve a tie --
8001             # for use by the party ranking calculations.
8002              
8003 12         25 $global_choice_count_at_full_second_representation_level = 0 ;
8004 12         13 $global_actual_choice_at_second_representation_ranking = 0 ;
8005 12         40 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
8006             {
8007 79         109 $global_full_representation_ranking_for_actual_choice[ $actual_choice ] = $global_representation_ranking_for_actual_choice[ $actual_choice ] ;
8008 79 100       223 if ( $global_full_representation_ranking_for_actual_choice[ $actual_choice ] == 2 )
8009             {
8010 17         21 $global_actual_choice_at_second_representation_ranking = $actual_choice ;
8011 17         36 $global_choice_count_at_full_second_representation_level ++ ;
8012             }
8013             }
8014 12 100       28 if ( $global_choice_count_at_full_second_representation_level != 1 )
8015             {
8016 6         13 $global_actual_choice_at_second_representation_ranking = 0 ;
8017             }
8018 12 50       70 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, number of second-most-representative choices is " . $global_choice_count_at_full_second_representation_level . "]\n" } ;
  12         41  
8019 12 50       30 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, if only one top choice, choice number is " . $global_actual_choice_at_second_representation_ranking . "]\n" } ;
  12         33  
8020              
8021              
8022             #-----------------------------------------------
8023             # If VoteFair party ranking results
8024             # have been requested, calculate them.
8025              
8026 12 50       31 if ( $global_true_or_false_request_votefair_party_rank == $global_true )
8027             {
8028 12 100       36 if ( $total_vote_count_for_current_question < 3 )
8029             {
8030 2         7 $global_output_warning_messages_case_or_question_specific .= $global_question_specific_warning_begin . " has-fewer-than-three-ballots-so-VoteFair-party-ranking-cannot-be-done" . "\n-----\n\n" ;
8031 2 50       7 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, not at least three ballots, so no party ranking done]\n" } ;
  2         6  
8032             } else
8033             {
8034 10         20 $global_ranking_type_being_calculated = "party" ;
8035 10 50       21 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, VoteFair party ranking calculations beginning]\n" } ;
  10         20  
8036 10         27 &calc_votefair_party_rank( ) ;
8037 10 50       32 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, VoteFair party ranking calculations done]\n" } ;
  10         34  
8038             }
8039             }
8040             }
8041              
8042              
8043             #-----------------------------------------------
8044             # Output the VoteFair Ranking results, which may
8045             # include: VoteFair popularity ranking
8046             # results, VoteFair representation ranking
8047             # results, and VoteFair popularity ranking results.
8048              
8049 18         66 &output_ranking_results( ) ;
8050 18 50       47 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, all done for question " . $global_question_number . " in case " . $global_case_number . "]\n" } ;
  18         65  
8051              
8052              
8053             #-----------------------------------------------
8054             # In the log file show a comparison of the
8055             # results for different ranking methods:
8056             # popularity, representation, and party.
8057              
8058 18 50 33     110 if ( ( $global_logging_info == $global_true ) && ( ( $global_true_or_false_request_votefair_popularity_rank == $global_true ) || ( $global_true_or_false_request_votefair_representation_rank == $global_true ) ) )
      33        
8059             {
8060 18         28 $possible_text_rep_not_the_same = "rep same" ;
8061 18         33 $possible_text_party_not_the_same = "par same" ;
8062 18         56 $comparison_of_methods_table = "[one question, case " . $global_case_number . " , question " . $global_question_number . " , comparison of popularity, representation, and party ranking]\n" ;
8063 18         62 for ( $sequence_position = 1 ; $sequence_position <= $global_full_choice_count + 1 ; $sequence_position ++ )
8064             {
8065 120         179 $popularity_level = $sequence_position ;
8066 120 100       263 if ( $sequence_position == $global_full_choice_count + 1 )
8067             {
8068 18         29 $popularity_level = 0 ;
8069             }
8070 120         254 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
8071             {
8072 844 100       2322 if ( $popularity_level == $global_full_popularity_ranking_for_actual_choice[ $actual_choice ] )
8073             {
8074 102         137 $representation_level = $global_full_representation_ranking_for_actual_choice[ $actual_choice ] ;
8075 102         202 $comparison_of_methods_table .= "[ choice " . $actual_choice . " at popularity level " . $popularity_level . " , representation level " . $representation_level ;
8076 102 100       164 if ( $global_true_or_false_request_votefair_party_rank == $global_true )
8077             {
8078 86         110 $party_level = $global_party_ranking_for_actual_choice[ $actual_choice ] ;
8079 86         131 $comparison_of_methods_table .= " , party level " . $party_level ;
8080             } else
8081             {
8082 16         23 $party_level = $representation_level ;
8083             }
8084 102         105 $comparison_of_methods_table .= "]" ;
8085 102 100       203 if ( $popularity_level != $representation_level )
8086             {
8087 62         76 $possible_text_rep_not_the_same = "rep not same" ;
8088 62         73 $comparison_of_methods_table .= " **** " ;
8089             }
8090 102 100       205 if ( $representation_level != $party_level )
8091             {
8092 36         47 $possible_text_party_not_the_same = "par not same" ;
8093 36         41 $comparison_of_methods_table .= " **** " ;
8094             }
8095 102         272 $comparison_of_methods_table .= "\n" ;
8096             }
8097             }
8098             }
8099 18         49 $comparison_of_methods_table .= "[" . $possible_text_rep_not_the_same . "][" . $possible_text_party_not_the_same . "]\n\n" ;
8100 18         103 print LOGOUT $comparison_of_methods_table . "\n" ;
8101             }
8102              
8103              
8104             #-----------------------------------------------
8105             # All done.
8106              
8107 18 50       44 if ( $global_logging_info == $global_true ) { print LOGOUT "[one question, exiting subroutine]\n" } ;
  18         35  
8108 18         63 return ;
8109              
8110             }
8111              
8112              
8113              
8114              
8115             =head2 set_all_choices_as_used
8116              
8117             (Not exported, for internal use only.)
8118              
8119             Specifies that all the choices (for the current
8120             question) are used (non-ignored).
8121              
8122             =cut
8123              
8124             #-----------------------------------------------
8125             #-----------------------------------------------
8126             # set_all_choices_as_used
8127             #-----------------------------------------------
8128             #-----------------------------------------------
8129              
8130             sub set_all_choices_as_used
8131             {
8132 42     42 1 64 my $actual_choice ;
8133 42         155 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
8134             {
8135 274         548 $global_using_choice[ $actual_choice ] = $global_true ;
8136             }
8137 42 50       92 if ( $global_logging_info == $global_true ) { print LOGOUT "[setting all choices as used]\n" } ;
  42         65  
8138 42         62 return 1 ;
8139             }
8140              
8141              
8142              
8143              
8144             =head2 reset_ballot_info_and_tally_table
8145              
8146             (Not exported, for internal use only.)
8147              
8148             Restarts the counting of ballot information at
8149             the first ballot (in the current case).
8150             Also sets up the adjusted (alias) choice numbers
8151             and pair counters to exclude the choices being ignored.
8152             Also creates and initializes the tally table.
8153              
8154             =cut
8155              
8156             #-----------------------------------------------
8157             #-----------------------------------------------
8158             # reset_ballot_info_and_tally_table
8159             #-----------------------------------------------
8160             #-----------------------------------------------
8161              
8162             sub reset_ballot_info_and_tally_table
8163             {
8164              
8165 106     106 1 149 my $actual_choice ;
8166             my $pair_counter ;
8167 0         0 my $adjusted_first_choice ;
8168 0         0 my $adjusted_second_choice ;
8169 0         0 my $adjusted_choice ;
8170              
8171              
8172             #-----------------------------------------------
8173             # Reset the ballot vote count.
8174              
8175 106         135 $global_ballot_info_repeat_count = 0 ;
8176 106         148 $global_current_total_vote_count = 0 ;
8177              
8178              
8179             #-----------------------------------------------
8180             # Reset the value that normally counts each
8181             # ballot as having one vote.
8182             # At some steps in VoteFair representation
8183             # ranking it is set to a value less than one
8184             # for some ballots (based on how the voter
8185             # ranked choices that have already been
8186             # identified as winning choices).
8187              
8188 106         118 $global_ballot_influence_amount = 1.0 ;
8189              
8190              
8191             #-----------------------------------------------
8192             # Log which choices are not being used.
8193              
8194 106         324 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
8195             {
8196 865 100       2299 if ( $global_using_choice[ $actual_choice ] == $global_false )
8197             {
8198 264 50       494 if ( $global_logging_info == $global_true ) { print LOGOUT "[ignoring choice " . $actual_choice . "]" } ;
  264         892  
8199             }
8200             }
8201              
8202              
8203             #-----------------------------------------------
8204             # Set up the adjusted choice numbers, and the
8205             # adjusted choice count.
8206              
8207 106         139 $global_adjusted_choice_count = 0 ;
8208 106         269 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
8209             {
8210 865 100       2045 if ( $global_using_choice[ $actual_choice ] == $global_true )
8211             {
8212 601         640 $global_adjusted_choice_count ++ ;
8213 601         717 $global_adjusted_choice_for_actual_choice[ $actual_choice ] = $global_adjusted_choice_count ;
8214 601         636 $global_actual_choice_for_adjusted_choice[ $global_adjusted_choice_count ] = $actual_choice ;
8215 601 50       1108 if ( $global_logging_info == $global_true ) { print LOGOUT "[adjusted choice " . $global_adjusted_choice_count . " corresponds to actual choice " . $actual_choice . "]" } ;
  601         2326  
8216             }
8217             }
8218 106 50       221 if ( $global_logging_info == $global_true ) { print LOGOUT "[adjusted choice count is " . $global_adjusted_choice_count . "]\n" } ;
  106         233  
8219              
8220              
8221             #-----------------------------------------------
8222             # Create the pairwise choice counters.
8223             # Also create an offset indexing that allows
8224             # the appropriate pair-counter number to be
8225             # easily calculated when the two choice
8226             # numbers are known.
8227              
8228 106         169 $pair_counter = 0 ;
8229 106         136 $global_pair_counter_maximum = 0 ;
8230 106         302 for ( $adjusted_first_choice = 1 ; $adjusted_first_choice < $global_adjusted_choice_count ; $adjusted_first_choice ++ )
8231             {
8232 495         673 $global_pair_counter_offset_for_first_adjusted_choice[ $adjusted_first_choice ] = $pair_counter - $adjusted_first_choice ;
8233 495         1086 for ( $adjusted_second_choice = $adjusted_first_choice + 1 ; $adjusted_second_choice <= $global_adjusted_choice_count ; $adjusted_second_choice ++ )
8234             {
8235 1697         1616 $pair_counter ++ ;
8236 1697         1563 $global_pair_counter_maximum ++ ;
8237 1697         1907 $global_adjusted_first_choice_number_in_pair[ $pair_counter ] = $adjusted_first_choice ;
8238 1697         4538 $global_adjusted_second_choice_number_in_pair[ $pair_counter ] = $adjusted_second_choice ;
8239             }
8240             }
8241              
8242              
8243             #-----------------------------------------------
8244             # Create, and clear, the tally table.
8245              
8246 106         318 for ( $pair_counter = 1 ; $pair_counter <= $global_pair_counter_maximum ; $pair_counter ++ )
8247             {
8248 1697         1767 $global_tally_first_over_second_in_pair[ $pair_counter ] = 0 ;
8249 1697         1685 $global_tally_second_over_first_in_pair[ $pair_counter ] = 0 ;
8250 1697         3436 $global_tally_first_equal_second_in_pair[ $pair_counter ] = 0 ;
8251             }
8252 106         175 $global_true_or_false_tally_table_created = $global_true ;
8253              
8254              
8255             #-----------------------------------------------
8256             # Initialize the plurality counts.
8257              
8258 106         267 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
8259             {
8260 601         640 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
8261 601         1254 $global_plurality_count_for_actual_choice[ $actual_choice ] = 0 ;
8262             }
8263              
8264              
8265             #-----------------------------------------------
8266             # Reset the pointer to the beginning of the
8267             # ballots for the current case.
8268              
8269 106         167 $global_pointer_to_current_ballot = $global_input_pointer_start_next_case ;
8270              
8271              
8272             # All done.
8273              
8274 106         165 return 1 ;
8275              
8276             }
8277              
8278              
8279              
8280              
8281             =head2 get_numbers_based_on_one_ballot
8282              
8283             (Not exported, for internal use only.)
8284              
8285             Gets the preference information from the next
8286             ballot. This information may include an optional
8287             multiple-ballot count that indicates how many
8288             ballots have the same specified preferences.
8289              
8290             =cut
8291              
8292             #-----------------------------------------------
8293             #-----------------------------------------------
8294             # get_numbers_based_on_one_ballot
8295             #-----------------------------------------------
8296             #-----------------------------------------------
8297              
8298             sub get_numbers_based_on_one_ballot
8299             {
8300              
8301 599     599 1 678 my $current_vote_info_number ;
8302             my $next_vote_info_number ;
8303 0         0 my $current_question_number ;
8304 0         0 my $preference_level ;
8305 0         0 my $choice_number ;
8306 0         0 my $choice_at_top_preference_level ;
8307 0         0 my $choice_count_at_top_preference_level ;
8308 0         0 my $count_of_encountered_ballot_counts ;
8309 0         0 my $text_ballot_info ;
8310              
8311              
8312             #-----------------------------------------------
8313             # Initialization.
8314              
8315 599         754 $current_question_number = 0 ;
8316 599         647 $choice_number = 0 ;
8317 599         647 $count_of_encountered_ballot_counts = 0 ;
8318 599         578 $choice_count_at_top_preference_level = 0 ;
8319 599         614 $choice_at_top_preference_level = 0 ;
8320 599         588 $preference_level = 1 ;
8321              
8322              
8323             #-----------------------------------------------
8324             # In case any of the choice numbers are not
8325             # encountered, initialize all the preference
8326             # levels to the last level.
8327              
8328 599         1345 for ( $choice_number = 1 ; $choice_number <= $global_full_choice_count ; $choice_number ++ )
8329             {
8330 4760         9717 $global_ballot_preference_for_choice[ $choice_number ] = $global_full_choice_count ;
8331             }
8332              
8333              
8334             #-----------------------------------------------
8335             # If the pointer is already at the end of the
8336             # ballots, return with a value of zero.
8337              
8338 599         756 $current_vote_info_number = $global_vote_info_list[ $global_pointer_to_current_ballot ] ;
8339 599 100 100     3689 if ( ( $current_vote_info_number == $global_voteinfo_code_for_end_of_all_vote_info ) || ( $current_vote_info_number == $global_voteinfo_code_for_case_number ) || ( $current_vote_info_number == $global_voteinfo_code_for_end_of_all_cases ) )
      100        
8340             {
8341 106         245 $global_ballot_info_repeat_count = 0 ;
8342 106 50       271 if ( $global_logging_info == $global_true ) { print LOGOUT "[end of ballots]\n" } ;
  106         224  
8343 106         290 return 0 ;
8344             }
8345              
8346              
8347             #-----------------------------------------------
8348             # Initially assume that the ballot count is
8349             # one.
8350              
8351 493         546 $global_ballot_info_repeat_count = 1 ;
8352 493         758 $text_ballot_info = "q " . $global_question_number . " " ;
8353              
8354              
8355             #-----------------------------------------------
8356             # Repeat a loop that handles each vote-info
8357             # number within one ballot.
8358              
8359 493         999 while ( $global_pointer_to_current_ballot < $global_max_array_length )
8360             {
8361              
8362              
8363             #-----------------------------------------------
8364             # Get the current vote-info number and, just in
8365             # case it's needed, the one after it.
8366              
8367 4143         4825 $current_vote_info_number = $global_vote_info_list[ $global_pointer_to_current_ballot ] ;
8368 4143 50       6694 if ( $global_pointer_to_current_ballot < $global_max_array_length - 1 )
8369             {
8370 4143         5613 $next_vote_info_number = $global_vote_info_list[ $global_pointer_to_current_ballot + 1 ] ;
8371             } else
8372             {
8373 0         0 $next_vote_info_number = 0 ;
8374             }
8375              
8376              
8377             #-----------------------------------------------
8378             # If the end of all the vote info, or the next
8379             # case number, or the end of all the cases,
8380             # has been reached, exit the loop.
8381              
8382 4143 100 100     36156 if ( ( $current_vote_info_number == $global_voteinfo_code_for_end_of_all_vote_info ) || ( $current_vote_info_number == $global_voteinfo_code_for_case_number ) || ( $current_vote_info_number == $global_voteinfo_code_for_end_of_all_cases ) )
    100 100        
    100 100        
    100          
    100          
    100          
8383             {
8384 106         187 last ;
8385              
8386              
8387             #-----------------------------------------------
8388             # When the end of the ballot is reached, point
8389             # to the beginning of the next ballot and exit
8390             # the loop.
8391              
8392             } elsif ( $current_vote_info_number == $global_voteinfo_code_for_end_of_ballot )
8393             {
8394 4         5 $global_pointer_to_current_ballot ++ ;
8395 4         8 last ;
8396              
8397              
8398             #-----------------------------------------------
8399             # If a ballot count (see next section) has been
8400             # encountered for a second time, the beginning
8401             # of the next ballot has been reached, so leave
8402             # the pointer pointing to the beginning of this
8403             # next ballot and exit the loop.
8404              
8405             } elsif ( ( $current_vote_info_number == $global_voteinfo_code_for_ballot_count ) && ( $count_of_encountered_ballot_counts > 0 ) )
8406             {
8407 383         537 last ;
8408              
8409              
8410             #-----------------------------------------------
8411             # Get the count for the number of identical
8412             # ballots (that have the same ranking sequence).
8413             # This vote count will be returned, or a value
8414             # of zero will be returned when there are no
8415             # more ballots encountered. Also count a
8416             # second ballot count in case an end-of-ballot
8417             # code is not used at the end of each ballot.
8418              
8419             } elsif ( $current_vote_info_number == $global_voteinfo_code_for_ballot_count )
8420             {
8421 493         619 $global_ballot_info_repeat_count = $next_vote_info_number ;
8422 493         473 $global_pointer_to_current_ballot ++ ;
8423 493         591 $count_of_encountered_ballot_counts ++ ;
8424              
8425              
8426             #-----------------------------------------------
8427             # Get the question number for the current
8428             # vote-info preference information.
8429              
8430             } elsif ( $current_vote_info_number == $global_voteinfo_code_for_question_number )
8431             {
8432 497         546 $current_question_number = $next_vote_info_number ;
8433 497         619 $global_pointer_to_current_ballot ++ ;
8434              
8435              
8436             #-----------------------------------------------
8437             # If the current preference levels do not apply
8438             # to the question being handled, skip ahead
8439             # over the handling of other codes.
8440              
8441             } elsif ( $current_question_number == $global_question_number )
8442             {
8443              
8444              
8445             #-----------------------------------------------
8446             # If a preference level is explicitly supplied,
8447             # adjust the preference level.
8448              
8449 2647 100       13200 if ( $current_vote_info_number == $global_voteinfo_code_for_preference_level )
    100          
    100          
8450             {
8451 12         15 $preference_level = $next_vote_info_number ;
8452 12         17 $global_pointer_to_current_ballot ++ ;
8453              
8454              
8455             #-----------------------------------------------
8456             # Adjust the preference level at tied levels.
8457              
8458             } elsif ( $current_vote_info_number == $global_voteinfo_code_for_tie )
8459             {
8460 83         105 $preference_level -- ;
8461 83 100       187 if ( $preference_level == 1 )
8462             {
8463 18         20 $choice_count_at_top_preference_level ++ ;
8464 18         20 $choice_at_top_preference_level = 0 ;
8465             }
8466 83         124 $text_ballot_info .= " tie" ;
8467              
8468              
8469             #-----------------------------------------------
8470             # For a choice number, determine its preference
8471             # level.
8472             # If this choice is at the top preference level,
8473             # save it -- for possible use in plurality
8474             # counting.
8475              
8476             } elsif ( $current_vote_info_number > 0 )
8477             {
8478 2544         2721 $choice_number = $current_vote_info_number ;
8479 2544         2840 $global_ballot_preference_for_choice[ $choice_number ] = $preference_level ;
8480 2544         3107 $text_ballot_info .= " " . $choice_number ;
8481 2544 100       5063 if ( $preference_level == 1 )
8482             {
8483 511         502 $choice_count_at_top_preference_level ++ ;
8484 511         687 $choice_at_top_preference_level = $choice_number ;
8485             }
8486 2544         3148 $preference_level ++ ;
8487             }
8488              
8489              
8490             #-----------------------------------------------
8491             # Finish skipping over the handling of codes
8492             # that do not apply to the question being
8493             # handled.
8494              
8495             }
8496              
8497              
8498             #-----------------------------------------------
8499             # Repeat the loop to handle the next
8500             # vote-info number.
8501              
8502 3650         7594 $global_pointer_to_current_ballot ++ ;
8503             }
8504              
8505              
8506             #-----------------------------------------------
8507             # If there was only one choice at the top
8508             # preference level, increment the plurality
8509             # count for that choice.
8510              
8511 493 100 66     1789 if ( ( $choice_count_at_top_preference_level == 1 ) && ( $choice_at_top_preference_level > 0 ) )
8512             {
8513 475         653 $global_plurality_count_for_actual_choice[ $choice_at_top_preference_level ] += $global_ballot_info_repeat_count ;
8514             }
8515              
8516              
8517             #-----------------------------------------------
8518             # Accumulate the total ballot vote count.
8519              
8520 493         529 $global_current_total_vote_count += $global_ballot_info_repeat_count ;
8521              
8522              
8523             #-----------------------------------------------
8524             # Return with the number of ballot counts
8525             # handled. If zero, there are no
8526             # more ballots in this question.
8527              
8528 493 50       966 if ( $global_logging_info == $global_true ) { print LOGOUT "[x " . $global_ballot_info_repeat_count . " " . $text_ballot_info . "]" } ;
  493         1177  
8529 493         1295 return $global_ballot_info_repeat_count ;
8530              
8531              
8532             #-----------------------------------------------
8533             # End of subroutine.
8534              
8535             }
8536              
8537              
8538              
8539              
8540             =head2 add_preferences_to_tally_table
8541              
8542             (Not exported, for internal use only.)
8543              
8544             Adds to the tally table the just-acquired
8545             preference numbers (from the current ballot).
8546              
8547             =cut
8548              
8549             #-----------------------------------------------
8550             #-----------------------------------------------
8551             # add_preferences_to_tally_table
8552             #-----------------------------------------------
8553             #-----------------------------------------------
8554              
8555             sub add_preferences_to_tally_table
8556             {
8557              
8558 364     364 1 419 my $pair_counter ;
8559             my $adjusted_first_choice ;
8560 0         0 my $adjusted_second_choice ;
8561 0         0 my $actual_first_choice ;
8562 0         0 my $actual_second_choice ;
8563 0         0 my $tally_amount ;
8564              
8565              
8566             #-----------------------------------------------
8567             # Update the tally table with the current ballot information.
8568             # Normally the influence amount is one, but it can be
8569             # a fractional vote in some VoteFair representation
8570             # calculations.
8571              
8572 364         467 $tally_amount = $global_ballot_info_repeat_count * $global_ballot_influence_amount ;
8573 364         808 for ( $pair_counter = 1 ; $pair_counter <= $global_pair_counter_maximum ; $pair_counter ++ )
8574             {
8575 5359         5653 $adjusted_first_choice = $global_adjusted_first_choice_number_in_pair[ $pair_counter ] ;
8576 5359         5693 $adjusted_second_choice = $global_adjusted_second_choice_number_in_pair[ $pair_counter ] ;
8577 5359         6646 $actual_first_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_first_choice ] ;
8578 5359         5419 $actual_second_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_second_choice ] ;
8579 5359 100       10458 if ( $global_ballot_preference_for_choice[ $actual_first_choice ] < $global_ballot_preference_for_choice[ $actual_second_choice ] )
    100          
8580             {
8581 2248         5303 $global_tally_first_over_second_in_pair[ $pair_counter ] += $tally_amount ;
8582             } elsif ( $global_ballot_preference_for_choice[ $actual_first_choice ] > $global_ballot_preference_for_choice[ $actual_second_choice ] )
8583             {
8584 2054         4954 $global_tally_second_over_first_in_pair[ $pair_counter ] += $tally_amount ;
8585             } else
8586             {
8587 1057         2436 $global_tally_first_equal_second_in_pair[ $pair_counter ] += $tally_amount ;
8588             }
8589             }
8590              
8591              
8592             #-----------------------------------------------
8593             # End of subroutine.
8594              
8595 364         675 return 1 ;
8596              
8597             }
8598              
8599              
8600              
8601              
8602              
8603             =head2 internal_view_matrix
8604              
8605             (Not exported, for internal use only.)
8606              
8607             For debugging purposes, writes to the debug log
8608             a matrix with the pairwise counts.
8609              
8610             =cut
8611              
8612             #-----------------------------------------------
8613             #-----------------------------------------------
8614             # internal_view_matrix
8615             #-----------------------------------------------
8616             #-----------------------------------------------
8617              
8618             sub internal_view_matrix
8619             {
8620              
8621 1910     1910 1 2266 my $matrix_row_number ;
8622             my $matrix_column_number ;
8623 0         0 my $sequence_string ;
8624 0         0 my $pair_counter ;
8625 0         0 my $adjusted_first_choice ;
8626 0         0 my $adjusted_second_choice ;
8627 0         0 my $actual_first_choice ;
8628 0         0 my $actual_second_choice ;
8629 0         0 my $text_count ;
8630 0         0 my $tally ;
8631 0         0 my $opposition_score ;
8632 0         0 my $text_count_decimal ;
8633 0         0 my $percentage ;
8634              
8635              
8636             #-----------------------------------------------
8637             # The sequence must be indicated in the list named
8638             # global_log_info_choice_at_position.
8639             # The number of choices is determined by the value
8640             # of global_adjusted_choice_count.
8641              
8642              
8643             #-----------------------------------------------
8644             # Display the tally numbers in a matrix.
8645              
8646 1910 50       4066 if ( $global_logging_info == $global_true )
8647             {
8648 1910         2636 $sequence_string = "" ;
8649 1910         2382 $global_pairwise_matrix_text = "" ;
8650 1910         2051 $global_sequence_score = 0 ;
8651 1910         2084 $opposition_score = 0 ;
8652 1910 100 66     8992 if ( ( not( defined( $global_scale_for_logged_pairwise_counts ) ) ) || ( $global_scale_for_logged_pairwise_counts < 0.000001 ) )
8653             {
8654 1         2 $global_scale_for_logged_pairwise_counts = 1.0 ;
8655             }
8656 1910         4013 for ( $matrix_row_number = 1 ; $matrix_row_number <= $global_adjusted_choice_count ; $matrix_row_number ++ )
8657             {
8658 11471         13851 $actual_first_choice = $global_log_info_choice_at_position[ $matrix_row_number ] ;
8659 11471         12185 $adjusted_first_choice = $global_adjusted_choice_for_actual_choice[ $actual_first_choice ] ;
8660 11471         16261 $sequence_string .= $actual_first_choice . " , " ;
8661 11471         13176 $global_pairwise_matrix_text .= "[" ;
8662 11471         22531 for ( $matrix_column_number = 1 ; $matrix_column_number <= $global_adjusted_choice_count ; $matrix_column_number ++ )
8663             {
8664 79019         107104 $actual_second_choice = $global_log_info_choice_at_position[ $matrix_column_number ] ;
8665 79019         90452 $adjusted_second_choice = $global_adjusted_choice_for_actual_choice[ $actual_second_choice ] ;
8666 79019         78297 $tally = 0 ;
8667 79019 100       159359 if ( $actual_first_choice == $actual_second_choice )
    100          
8668             {
8669 11471         12944 $text_count = " ---" ;
8670 11471         14808 $text_count_decimal = " ----- " ;
8671             } elsif ( $actual_first_choice < $actual_second_choice )
8672             {
8673 33774         37677 $pair_counter = $global_pair_counter_offset_for_first_adjusted_choice[ $adjusted_first_choice ] + $adjusted_second_choice ;
8674 33774         38209 $tally = $global_tally_first_over_second_in_pair[ $pair_counter ] * $global_scale_for_logged_pairwise_counts ;
8675 33774         60735 $text_count = sprintf( "%4d" , $tally ) ;
8676 33774         104219 $text_count_decimal = sprintf( "%6.2f" , $tally ) ;
8677             } else
8678             {
8679 33774         39887 $pair_counter = $global_pair_counter_offset_for_first_adjusted_choice[ $adjusted_second_choice ] + $adjusted_first_choice ;
8680 33774         47455 $tally = $global_tally_second_over_first_in_pair[ $pair_counter ] * $global_scale_for_logged_pairwise_counts ;
8681 33774         60715 $text_count = sprintf( "%4d" , $tally ) ;
8682 33774         113135 $text_count_decimal = sprintf( "%6.2f" , $tally ) ;
8683             }
8684 79019         114896 $global_pairwise_matrix_text .= " " . $text_count . " " ;
8685 79019 100       121599 if ( $matrix_column_number > $matrix_row_number )
8686             {
8687 33774         96724 $global_sequence_score += $tally ;
8688             } else
8689             {
8690 45245         105427 $opposition_score += $tally ;
8691             }
8692             }
8693 11471         26896 $global_pairwise_matrix_text .= "]\n" ;
8694             }
8695 1910 50       3251 if ( $global_sequence_score + $opposition_score > 0 )
8696             {
8697 1910         3194 $percentage = ( $global_sequence_score / ( $global_sequence_score + $opposition_score ) ) * 100 ;
8698             } else
8699             {
8700 0         0 $percentage = 0 ;
8701             }
8702 1910         11880 $sequence_string =~ s/, *$// ;
8703 1910         5622 $global_pairwise_matrix_text .= "\n" . "[above counts apply to sequence: " . $sequence_string . "] [seq score = " . sprintf( "%6d" , $global_sequence_score ) . "]\n" ;
8704 1910         3684 $global_pairwise_matrix_text .= "[percent support: " . sprintf( "%4d" , $percentage ) . "]\n" ;
8705 1910         12000 print LOGOUT "\n" . $global_pairwise_matrix_text . "\n" ;
8706             }
8707              
8708              
8709             #-----------------------------------------------
8710             # Reset the scale value in case it is not
8711             # reset elsewhere.
8712              
8713 1910         2301 $global_scale_for_logged_pairwise_counts = 1.0 ;
8714              
8715              
8716             #-----------------------------------------------
8717             # End of subroutine.
8718              
8719 1910         3125 return 1 ;
8720              
8721             }
8722              
8723              
8724              
8725              
8726             =head2 normalize_ranking
8727              
8728             (Not exported, for internal use only.)
8729              
8730             Normalizes ranking levels so that ranking levels
8731             are sequential integer numbers (with no numbers
8732             skipped).
8733              
8734             =cut
8735              
8736             #-----------------------------------------------
8737             #-----------------------------------------------
8738             # normalize_ranking
8739             #-----------------------------------------------
8740             #-----------------------------------------------
8741              
8742             sub normalize_ranking
8743             {
8744              
8745 224     224 1 336 my $adjusted_choice ;
8746             my $actual_choice ;
8747 0         0 my $ranking_level ;
8748 0         0 my $previous_ranking_level ;
8749 0         0 my $new_ranking_level ;
8750 0         0 my $sequence_position ;
8751 0         0 my $true_or_false_log_details ;
8752              
8753 0         0 my @new_rank_for_adjusted_choice ;
8754 0         0 my %adjusted_choice_at_ranking_level ;
8755              
8756              
8757             #-----------------------------------------------
8758             # Hide (or show) details.
8759              
8760 224         304 $true_or_false_log_details = $global_false ;
8761              
8762              
8763             #-----------------------------------------------
8764             # For each adjusted choice, get its ranking
8765             # level, and index those ranking levels.
8766             # If there is only one choice at a ranking
8767             # level, store the adjusted choice number at
8768             # that level.
8769              
8770 224         559 %adjusted_choice_at_ranking_level = ( ) ;
8771 224 50       626 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[normalization, un-normalized values:]\n" } ;
  0         0  
8772 224         635 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
8773             {
8774 1188         1361 $ranking_level = $global_rank_to_normalize_for_adjusted_choice[ $adjusted_choice ] ;
8775 1188         2744 $adjusted_choice_at_ranking_level{ $ranking_level } ++ ;
8776 1188 50       2185 if ( defined( $adjusted_choice_at_ranking_level{ $ranking_level } ) )
8777             {
8778 1188         1837 $adjusted_choice_at_ranking_level{ $ranking_level } = 0 ;
8779             } else
8780             {
8781 0         0 $adjusted_choice_at_ranking_level{ $ranking_level } = $adjusted_choice ;
8782             }
8783 1188         1284 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
8784 1188 50       4089 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[ choice " . $actual_choice . " at level " . $ranking_level . "]\n" } ;
  0         0  
8785             }
8786              
8787              
8788             #-----------------------------------------------
8789             # Normalize the ranking levels so that no
8790             # ranking levels are skipped.
8791             # While doing this, put into the
8792             # global_log_info_choice_at_position
8793             # list the actual choice numbers in the
8794             # calculated sequence -- so that the
8795             # internal_view_matrix subroutine can use this
8796             # sequence to display the normalized results.
8797              
8798 224         272 $new_ranking_level = 1 ;
8799 224         321 $sequence_position = 1 ;
8800             # Possibly modify code in next line to allow easier future conversion to C language.
8801 224         5737 foreach $previous_ranking_level ( sort {$a <=> $b} keys( %adjusted_choice_at_ranking_level ) )
  1682         2620  
8802             {
8803 1072 50       2092 if ( $adjusted_choice_at_ranking_level{ $previous_ranking_level } != 0 )
8804             {
8805 0         0 $adjusted_choice = $adjusted_choice_at_ranking_level{ $previous_ranking_level } ;
8806 0         0 $new_rank_for_adjusted_choice[ $adjusted_choice ] = $new_ranking_level ;
8807 0 0       0 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[normalization, changed rank of choice " . $adjusted_choice . " to level " . $new_ranking_level . "]\n" } ;
  0         0  
8808             } else
8809             {
8810 1072         2464 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
8811             {
8812 6751 100       17931 if ( $global_rank_to_normalize_for_adjusted_choice[ $adjusted_choice ] == $previous_ranking_level )
8813             {
8814 1188         1710 $new_rank_for_adjusted_choice[ $adjusted_choice ] = $new_ranking_level ;
8815 1188         1419 $actual_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_choice ] ;
8816 1188         1325 $global_log_info_choice_at_position[ $sequence_position ] = $actual_choice ;
8817 1188         1143 $sequence_position ++ ;
8818 1188 50       3708 if ( $true_or_false_log_details == $global_true ) { print LOGOUT "[normalization, changed rank of choice " . $actual_choice . " to level " . $new_ranking_level . "]\n" } ;
  0         0  
8819             }
8820             }
8821             }
8822 1072         1697 $new_ranking_level ++ ;
8823             }
8824              
8825              
8826             #-----------------------------------------------
8827             # Copy the results back to the globally
8828             # accessible array.
8829              
8830 224         821 for ( $adjusted_choice = 1 ; $adjusted_choice <= $global_adjusted_choice_count ; $adjusted_choice ++ )
8831             {
8832 1188         2462 $global_rank_to_normalize_for_adjusted_choice[ $adjusted_choice ] = $new_rank_for_adjusted_choice[ $adjusted_choice ] ;
8833             }
8834              
8835              
8836             #-----------------------------------------------
8837             # End of subroutine.
8838              
8839 224         844 return ;
8840              
8841             }
8842              
8843              
8844              
8845              
8846             =head2 put_next_result_info_number
8847              
8848             (Not exported, for internal use only.)
8849              
8850             Puts the next result-info number into the array
8851             that stores the result information.
8852              
8853             =cut
8854              
8855             #-----------------------------------------------
8856             #-----------------------------------------------
8857             # put_next_result_info_number
8858             #-----------------------------------------------
8859             #-----------------------------------------------
8860              
8861             sub put_next_result_info_number
8862             {
8863              
8864 2682     2682 1 2568 my $current_result_info_number ;
8865              
8866              
8867             #-----------------------------------------------
8868             # Get the supplied value.
8869              
8870 2682 50       4671 if ( scalar( @_ ) == 1 )
8871             {
8872 2682         3165 $current_result_info_number = $_[ 0 ] ;
8873             } else
8874             {
8875 0         0 warn "Error: No value supplied to the put_next_result_info_number subroutine" ;
8876 0         0 return ;
8877             }
8878              
8879              
8880             #-----------------------------------------------
8881             # If the list has become too long,
8882             # insert the code that indicates the end
8883             # of the results, and then indicate an error.
8884              
8885 2682 50       5089 if ( $global_pointer_to_output_results >= $global_max_array_length )
8886             {
8887 0         0 $global_output_results[ $global_pointer_to_output_results ] = $global_voteinfo_code_for_end_of_all_cases ;
8888 0         0 $global_possible_error_message = "Error: Not enough room for results from all cases (size limit is " . $global_max_array_length . ")" ;
8889 0         0 return ;
8890             }
8891              
8892              
8893             #-----------------------------------------------
8894             # Put the next result-info number into the list.
8895              
8896 2682         3864 $global_output_results[ $global_pointer_to_output_results ] = $current_result_info_number ;
8897              
8898              
8899             #-----------------------------------------------
8900             # Increment the list pointer, and increment the
8901             # length of the list.
8902              
8903 2682         2873 $global_pointer_to_output_results ++ ;
8904 2682         2662 $global_length_of_result_info_list = $global_pointer_to_output_results ;
8905              
8906              
8907             #-----------------------------------------------
8908             # End of subroutine.
8909              
8910 2682         3435 return ;
8911              
8912             }
8913              
8914              
8915              
8916              
8917             =head2 output_plurality_counts
8918              
8919             (Not exported, for internal use only.)
8920              
8921             Puts into the output results the plurality counts.
8922              
8923             =cut
8924              
8925             #-----------------------------------------------
8926             #-----------------------------------------------
8927             # output_plurality_counts
8928             #-----------------------------------------------
8929             #-----------------------------------------------
8930              
8931             sub output_plurality_counts
8932             {
8933              
8934 19     19 1 26 my $actual_choice ;
8935              
8936              
8937             #-----------------------------------------------
8938             # Put the plurality counts into the output
8939             # results list.
8940              
8941 19         44 &put_next_result_info_number( $global_voteinfo_code_for_start_of_plurality_results ) ;
8942 19 50       50 if ( $global_logging_info == $global_true ) { print LOGOUT "[output, plurality counts:]\n" } ;
  19         43  
8943 19         53 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
8944             {
8945 105         176 &put_next_result_info_number( $global_voteinfo_code_for_choice ) ;
8946 105         168 &put_next_result_info_number( $actual_choice ) ;
8947 105         182 &put_next_result_info_number( $global_voteinfo_code_for_plurality_count ) ;
8948 105         169 &put_next_result_info_number( $global_plurality_count_for_actual_choice[ $actual_choice ] ) ;
8949 105 100       210 if ( $global_plurality_count_for_actual_choice[ $actual_choice ] > 0 )
8950             {
8951 58 50       133 if ( $global_logging_info == $global_true ) { print LOGOUT "[output, plurality count for choice " . $actual_choice . " is " . $global_plurality_count_for_actual_choice[ $actual_choice ] . "]\n" } ;
  58         307  
8952             } else
8953             {
8954 47 50       123 if ( $global_logging_info == $global_true ) { print LOGOUT "[output, plurality count for choice " . $actual_choice . " is " . "0" . "]\n" } ;
  47         186  
8955             }
8956             }
8957 19         42 &put_next_result_info_number( $global_voteinfo_code_for_end_of_plurality_results ) ;
8958              
8959              
8960             #-----------------------------------------------
8961             # End of subroutine.
8962              
8963 19         24 return ;
8964              
8965             }
8966              
8967              
8968              
8969              
8970             =head2 output_tally_table_numbers
8971              
8972             (Not exported, for internal use only.)
8973              
8974             Puts the pairwise counts from the tally table
8975             into the output list.
8976              
8977             =cut
8978              
8979             #-----------------------------------------------
8980             #-----------------------------------------------
8981             # output_tally_table_numbers
8982             #-----------------------------------------------
8983             #-----------------------------------------------
8984              
8985             sub output_tally_table_numbers
8986             {
8987              
8988 5     5 1 8 my $adjusted_first_choice ;
8989             my $adjusted_second_choice ;
8990 0         0 my $actual_first_choice ;
8991 0         0 my $actual_second_choice ;
8992 0         0 my $pair_counter ;
8993              
8994              
8995             #-----------------------------------------------
8996             # This subroutine must be used while the pairwise
8997             # counts for all the choices are still in the
8998             # tally table.
8999              
9000              
9001             #-----------------------------------------------
9002             # Output the pairwise counts from the tally table.
9003              
9004 5         21 &put_next_result_info_number( $global_voteinfo_code_for_start_of_tally_table_results ) ;
9005 5         19 for ( $pair_counter = 1 ; $pair_counter <= $global_pair_counter_maximum ; $pair_counter ++ )
9006             {
9007 25         37 $adjusted_first_choice = $global_adjusted_first_choice_number_in_pair[ $pair_counter ] ;
9008 25         31 $adjusted_second_choice = $global_adjusted_second_choice_number_in_pair[ $pair_counter ] ;
9009              
9010 25         33 $actual_first_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_first_choice ] ;
9011 25         34 $actual_second_choice = $global_actual_choice_for_adjusted_choice[ $adjusted_second_choice ] ;
9012              
9013 25 50 33     114 if ( ( $adjusted_first_choice != $actual_first_choice ) || ( $adjusted_second_choice != $actual_second_choice ) )
9014             {
9015 0 0       0 if ( $global_logging_info == $global_true ) { print LOGOUT "[error: in output_tally_table_numbers subroutine, actual and adjusted choice numbers do not match]" } ;
  0         0  
9016 0         0 warn "Error: Subroutine output_tally_table_numbers used inappropriately" ;
9017 0         0 return ;
9018             }
9019              
9020 25         45 &put_next_result_info_number( $global_voteinfo_code_for_first_choice ) ;
9021 25         41 &put_next_result_info_number( $actual_first_choice ) ;
9022              
9023 25         39 &put_next_result_info_number( $global_voteinfo_code_for_second_choice ) ;
9024 25         42 &put_next_result_info_number( $actual_second_choice ) ;
9025              
9026 25         36 &put_next_result_info_number( $global_voteinfo_code_for_tally_first_over_second ) ;
9027 25         47 &put_next_result_info_number( $global_tally_first_over_second_in_pair[ $pair_counter ] ) ;
9028              
9029 25         44 &put_next_result_info_number( $global_voteinfo_code_for_tally_second_over_first ) ;
9030 25         48 &put_next_result_info_number( $global_tally_second_over_first_in_pair[ $pair_counter ] ) ;
9031              
9032             }
9033 5         17 &put_next_result_info_number( $global_voteinfo_code_for_end_of_tally_table_results ) ;
9034              
9035              
9036             #-----------------------------------------------
9037             # End of subroutine.
9038              
9039 5         11 return 1 ;
9040              
9041             }
9042              
9043              
9044              
9045              
9046             =head2 output_ranking_results
9047              
9048             (Not exported, for internal use only.)
9049              
9050             Outputs the results of the requested VoteFair
9051             Ranking results. These results are supplied in
9052             two forms: in their sequence order, and in order
9053             of their choice number.
9054              
9055             =cut
9056              
9057             #-----------------------------------------------
9058             #-----------------------------------------------
9059             # output_ranking_results
9060             #-----------------------------------------------
9061             #-----------------------------------------------
9062              
9063             sub output_ranking_results
9064             {
9065              
9066 18     18 1 39 my $actual_choice ;
9067             my $ranking_level ;
9068 0         0 my $ranking_type_name ;
9069 0         0 my $ranking_type_number ;
9070 0         0 my $ranking_type_number_for_popularity ;
9071 0         0 my $ranking_type_number_for_representation ;
9072 0         0 my $ranking_type_number_for_party ;
9073 0         0 my $start_code ;
9074 0         0 my $end_code ;
9075 0         0 my $count_of_ranked_choices ;
9076 0         0 my $sum_of_rankings ;
9077 0         0 my $count_of_choices_found_at_this_ranking_level ;
9078              
9079 0         0 my @ranking_type_number_for_popularity ;
9080 0         0 my @ranking_type_number_for_representation ;
9081 0         0 my @ranking_type_number_for_party ;
9082 0         0 my @ranking_type_name_for_number ;
9083 0         0 my @sequence_start_code_for_ranking_type ;
9084 0         0 my @sequence_end_code_for_ranking_type ;
9085 0         0 my @levels_start_code_for_ranking_type ;
9086 0         0 my @levels_end_code_for_ranking_type ;
9087 0         0 my @ranking_level_result_for_actual_choice ;
9088              
9089              
9090             #-----------------------------------------------
9091             # Set up lists that allow the different kinds
9092             # of ranking to have their associated code
9093             # numbers in indexed lists.
9094              
9095 18         26 $ranking_type_number_for_popularity = 1 ;
9096 18         38 $ranking_type_name_for_number[ $ranking_type_number_for_popularity ] = "popularity" ;
9097 18         31 $sequence_start_code_for_ranking_type[ $ranking_type_number_for_popularity ] = $global_voteinfo_code_for_start_of_votefair_popularity_ranking_sequence_results ;
9098 18         31 $sequence_end_code_for_ranking_type[ $ranking_type_number_for_popularity ] = $global_voteinfo_code_for_end_of_votefair_popularity_ranking_sequence_results ;
9099 18         24 $levels_start_code_for_ranking_type[ $ranking_type_number_for_popularity ] = $global_voteinfo_code_for_start_of_votefair_popularity_ranking_levels_results ;
9100 18         93 $levels_end_code_for_ranking_type[ $ranking_type_number_for_popularity ] = $global_voteinfo_code_for_end_of_votefair_popularity_ranking_levels_results ;
9101              
9102 18         23 $ranking_type_number_for_representation = 2 ;
9103 18         32 $ranking_type_name_for_number[ $ranking_type_number_for_representation ] = "representation" ;
9104 18         26 $sequence_start_code_for_ranking_type[ $ranking_type_number_for_representation ] = $global_voteinfo_code_for_start_of_votefair_representation_ranking_sequence_results ;
9105 18         34 $sequence_end_code_for_ranking_type[ $ranking_type_number_for_representation ] = $global_voteinfo_code_for_end_of_votefair_representation_ranking_sequence_results ;
9106 18         26 $levels_start_code_for_ranking_type[ $ranking_type_number_for_representation ] = $global_voteinfo_code_for_start_of_votefair_representation_ranking_levels_results ;
9107 18         26 $levels_end_code_for_ranking_type[ $ranking_type_number_for_representation ] = $global_voteinfo_code_for_end_of_votefair_representation_ranking_levels_results ;
9108              
9109 18         25 $ranking_type_number_for_party = 3 ;
9110 18         31 $ranking_type_name_for_number[ $ranking_type_number_for_party ] = "party" ;
9111 18         31 $sequence_start_code_for_ranking_type[ $ranking_type_number_for_party ] = $global_voteinfo_code_for_start_of_votefair_party_ranking_sequence_results ;
9112 18         24 $sequence_end_code_for_ranking_type[ $ranking_type_number_for_party ] = $global_voteinfo_code_for_end_of_votefair_party_ranking_sequence_results ;
9113 18         26 $levels_start_code_for_ranking_type[ $ranking_type_number_for_party ] = $global_voteinfo_code_for_start_of_votefair_party_ranking_levels_results ;
9114 18         28 $levels_end_code_for_ranking_type[ $ranking_type_number_for_party ] = $global_voteinfo_code_for_end_of_votefair_party_ranking_levels_results ;
9115              
9116              
9117             #-----------------------------------------------
9118             # Begin a loop that handles each of the three
9119             # different ranking types.
9120              
9121 18         61 for ( $ranking_type_number = 1 ; $ranking_type_number <= 3 ; $ranking_type_number ++ )
9122             {
9123 54         75 $ranking_type_name = $ranking_type_name_for_number[ $ranking_type_number ] ;
9124              
9125              
9126             #-----------------------------------------------
9127             # Copy the ranking levels for the kind of
9128             # ranking being sent to the code-number
9129             # output list.
9130              
9131 54         62 $sum_of_rankings = 0 ;
9132 54         169 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
9133             {
9134 306 100       683 if ( $ranking_type_number == $ranking_type_number_for_popularity )
    100          
    50          
9135             {
9136 102         184 $ranking_level_result_for_actual_choice[ $actual_choice ] = $global_full_popularity_ranking_for_actual_choice[ $actual_choice ] ;
9137             } elsif ( $ranking_type_number == $ranking_type_number_for_representation )
9138             {
9139 102         149 $ranking_level_result_for_actual_choice[ $actual_choice ] = $global_full_representation_ranking_for_actual_choice[ $actual_choice ] ;
9140             } elsif ( $ranking_type_number == $ranking_type_number_for_party )
9141             {
9142 102         136 $ranking_level_result_for_actual_choice[ $actual_choice ] = $global_party_ranking_for_actual_choice[ $actual_choice ] ;
9143             }
9144 306         839 $sum_of_rankings += $ranking_level_result_for_actual_choice[ $actual_choice ] ;
9145             }
9146              
9147              
9148             #-----------------------------------------------
9149             # If there are only zero ranking values,
9150             # create an error message, and skip the
9151             # outputting of these all-zero values.
9152              
9153 54 100       119 if ( $sum_of_rankings < 1 )
9154             {
9155 14 50       30 if ( $global_logging_info == $global_true ) { print LOGOUT "[output, all-zero results for " . $ranking_type_name . " ranking, so none written]\n" } ;
  14         104  
9156 14         44 next ;
9157             }
9158              
9159              
9160             #-----------------------------------------------
9161             # Output specified ranking results as coded
9162             # numbers in which each choice is associated
9163             # with a ranking level.
9164              
9165 40 50       95 if ( $global_logging_info == $global_true ) { print LOGOUT "[output, ranking results for " . $ranking_type_name . " ranking:]\n" } ;
  40         81  
9166 40         53 $start_code = $levels_start_code_for_ranking_type[ $ranking_type_number ] ;
9167 40         81 &put_next_result_info_number( $start_code ) ;
9168 40         111 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
9169             {
9170 256         333 $ranking_level = $ranking_level_result_for_actual_choice[ $actual_choice ] ;
9171 256         387 &put_next_result_info_number( $global_voteinfo_code_for_choice ) ;
9172 256         366 &put_next_result_info_number( $actual_choice ) ;
9173 256         404 &put_next_result_info_number( $global_voteinfo_code_for_ranking_level ) ;
9174 256         411 &put_next_result_info_number( $ranking_level ) ;
9175 256 50       509 if ( $global_logging_info == $global_true ) { print LOGOUT "[output, choice " . $actual_choice . " is at ranking level " . $ranking_level . "]\n" } ;
  256         993  
9176             }
9177 40         59 $end_code = $levels_end_code_for_ranking_type[ $ranking_type_number ] ;
9178 40         134 &put_next_result_info_number( $end_code ) ;
9179              
9180              
9181             #-----------------------------------------------
9182             # Output the ranking as a sequence of
9183             # choice numbers, with ties and transitions (to
9184             # the next ranking level) indicated.
9185              
9186 40 50       86 if ( $global_logging_info == $global_true ) { print LOGOUT "[output, sequence results for " . $ranking_type_name . " ranking:]\n" } ;
  40         84  
9187 40         58 $start_code = $sequence_start_code_for_ranking_type[ $ranking_type_number ] ;
9188 40         59 &put_next_result_info_number( $start_code ) ;
9189 40         47 $count_of_ranked_choices = 0 ;
9190 40         92 for ( $ranking_level = 1 ; $ranking_level <= $global_full_choice_count ; $ranking_level ++ )
9191             {
9192 256         308 $count_of_choices_found_at_this_ranking_level = 0 ;
9193 256         489 for ( $actual_choice = 1 ; $actual_choice <= $global_full_choice_count ; $actual_choice ++ )
9194             {
9195 2040 100       5639 if ( $ranking_level_result_for_actual_choice[ $actual_choice ] == $ranking_level )
9196             {
9197 244 100       535 if ( $count_of_choices_found_at_this_ranking_level > 0 )
    100          
9198             {
9199 71         111 &put_next_result_info_number( $global_voteinfo_code_for_tie ) ;
9200             } elsif ( $count_of_ranked_choices > 0 )
9201             {
9202 133         226 &put_next_result_info_number( $global_voteinfo_code_for_next_ranking_level ) ;
9203             }
9204 244         370 &put_next_result_info_number( $global_voteinfo_code_for_choice ) ;
9205 244         355 &put_next_result_info_number( $actual_choice ) ;
9206 244 50       450 if ( $global_logging_info == $global_true ) { print LOGOUT "[output, choice " . $actual_choice . " is next in sequence at ranking level " . $ranking_level . "]\n" } ;
  244         674  
9207 244         262 $count_of_choices_found_at_this_ranking_level ++ ;
9208 244         607 $count_of_ranked_choices ++ ;
9209             }
9210             }
9211             }
9212 40 100       93 if ( $count_of_ranked_choices < $global_full_choice_count )
9213             {
9214 3         29 &put_next_result_info_number( $global_voteinfo_code_for_early_end_of_ranking ) ;
9215             }
9216 40         66 $end_code = $sequence_end_code_for_ranking_type[ $ranking_type_number ] ;
9217 40         59 &put_next_result_info_number( $end_code ) ;
9218 40 50       85 if ( $global_logging_info == $global_true ) { print LOGOUT "[output, end of " . $ranking_type_name . " ranking sequence]\n" } ;
  40         154  
9219              
9220              
9221             #-----------------------------------------------
9222             # Repeat the loop that handles each type of
9223             # ranking.
9224              
9225             }
9226              
9227              
9228             #-----------------------------------------------
9229             # End of subroutine.
9230              
9231 18         75 return ;
9232              
9233             }
9234              
9235              
9236              
9237              
9238             =head1 AUTHOR
9239              
9240             Richard Fobes, C<< >>
9241              
9242              
9243             =head1 BUGS
9244              
9245             Please report any bugs or feature requests on GitHub, at the CPSolver account, in the VoteFairRanking project area. Thank you!
9246              
9247              
9248             =head1 SUPPORT
9249              
9250             You can find documentation for this module on GitHub, in the CPSolver account, in the VoteFairRanking project area.
9251              
9252             You can find details about VoteFair Ranking at: www.VoteFair.org
9253              
9254              
9255             =head1 ACKNOWLEDGEMENTS
9256              
9257             Richard Fobes designed VoteFair Ranking and developed the original version of this code over a period of many years. Richard Fobes is the author of the books titled "The Creative Problem Solver's Toolbox" and "Ending The Hidden Unfairness In U.S. Elections."
9258              
9259              
9260             =head1 COPYRIGHT & LICENSE
9261              
9262             (c) Copyright 1991 through 2011 Richard Fobes at www.VoteFair.org. You can redistribute and/or modify this VoteFairRanking library module under the Perl Artistic license version 2.0 (a copy of which is included in the LICENSE file). As required by the license this full copyright notice must be included in all copies of this software.
9263              
9264             Conversion of this code into another programming language is also covered by the above license terms.
9265              
9266             The mathematical algorithms of VoteFair Ranking are in the public domain.
9267              
9268             =cut
9269              
9270             1; # End of VoteFairRanking