+sub continuing () {
+ grep { !$_->{NonCont} } values %cands;
+}
+
+sub select_best_worst ($$$$) {
+ my ($wantcand, $wanttiebreak, $signum, $what) = @_;
+ # $wantcand->($c) = boolish
+ # $wanttiebreak->($total) = boolish
+ # Firstly candidates not meeting $wantcand are ignored
+ # Then we pick the best (worst) candiate by Total (or vote history).
+ # (SLGEO 49(2) and 51(2).
+ # If this does not help then totals are equal and we call wanttiebreak.
+ # If it returns 0 we return alphabetically first CAND. Otherwise
+ # we tie break.
+
+ my @maybe = grep { $wantcand->($_) } continuing();
+ @maybe = sort total_history_cmp @maybe;
+ @maybe = reverse @maybe if $signum > 0;
+
+ return undef unless @maybe;
+
+ my $nequal = 1;
+
+ for (;;) {
+ my $nextc = $maybe[$nequal];
+
+ # Only interested in those who compare equal according to the
+ # history (SLGEO 49(2)); NB our history includes the current
+ # round.
+
+ last if $signum*($a = $maybe[0], $b = $nextc, total_history_cmp) > 0;
+ $nextc++;
+ }
+
+ if ($nequal > 1 && !$wanttiebreak->($maybe[0]{Total})) {
+ # ... if equal for election we can do them one by one, since
+ # order does not matter (SLGEO 49 talks about `two or more
+ # ... exceeds').
+ $nequal = 1;
+ }
+
+ my $selectcand;
+ if ($nequal > 1) {
+ my @all = map { $_->{Cand} } @maybe[0 .. $nequal-1];
+ my $tiekey = $signum > 0 ? 'Win' : 'Lose';
+ $selectcand = $tie{"@all"}{$tiekey};
+ die "need tie break, want $tiekey from @all"
+ unless defined $selectcand;
+ prf "$what %s due to tie break amongst %s\n",
+ $selectcand, "@all";
+ } else {
+ $selectcand = $maybe[0]{Cand};
+ prf "$what %s\n", $selectcand;
+ }
+
+ return $cands{$selectcand};
+}
+